diff --git a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx index c79904661..d582b2d5b 100644 --- a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx @@ -17,191 +17,191 @@ import IntComponent from "../../../../components/intComponent"; import PromptAreaComponent from "../../../../components/promptComponent"; export default function ParameterComponent({ - left, - id, - data, - tooltipTitle, - title, - color, - type, - name = "", - required = false, + left, + id, + data, + tooltipTitle, + title, + color, + type, + name = "", + required = false, }: ParameterComponentType) { - const ref = useRef(null); - const updateNodeInternals = useUpdateNodeInternals(); - const [position, setPosition] = useState(0); - useEffect(() => { - if (ref.current && ref.current.offsetTop && ref.current.clientHeight) { - setPosition(ref.current.offsetTop + ref.current.clientHeight / 2); - updateNodeInternals(data.id); - } - }, [data.id, ref, updateNodeInternals]); + const ref = useRef(null); + const updateNodeInternals = useUpdateNodeInternals(); + const [position, setPosition] = useState(0); + useEffect(() => { + if (ref.current && ref.current.offsetTop && ref.current.clientHeight) { + setPosition(ref.current.offsetTop + ref.current.clientHeight / 2); + updateNodeInternals(data.id); + } + }, [data.id, ref, updateNodeInternals]); - useEffect(() => { - updateNodeInternals(data.id); - }, [data.id, position, updateNodeInternals]); + useEffect(() => { + updateNodeInternals(data.id); + }, [data.id, position, updateNodeInternals]); - const [enabled, setEnabled] = useState( - data.node.template[name]?.value ?? false - ); - const { reactFlowInstance } = useContext(typesContext); - let disabled = - reactFlowInstance?.getEdges().some((e) => e.targetHandle === id) ?? false; - const { save } = useContext(TabsContext); + const [enabled, setEnabled] = useState( + data.node.template[name]?.value ?? false + ); + const { reactFlowInstance } = useContext(typesContext); + let disabled = + reactFlowInstance?.getEdges().some((e) => e.targetHandle === id) ?? false; + const { save } = useContext(TabsContext); - return ( -
- <> -
- {title} - {required ? " *" : ""} -
- {left && - (type === "str" || - type === "bool" || - type === "float" || - type === "code" || - type === "prompt" || - type === "file" || - type === "int") ? ( - <> - ) : ( - - - isValidConnection(connection, reactFlowInstance) - } - className={classNames( - left ? "-ml-0.5 " : "-mr-0.5 ", - "w-3 h-3 rounded-full border-2 bg-white dark:bg-gray-800" - )} - style={{ - borderColor: color, - top: position, - }} - > - - )} + return ( +
+ <> +
+ {title} + {required ? " *" : ""} +
+ {left && + (type === "str" || + type === "bool" || + type === "float" || + type === "code" || + type === "prompt" || + type === "file" || + type === "int") ? ( + <> + ) : ( + + + isValidConnection(connection, reactFlowInstance) + } + className={classNames( + left ? "-ml-0.5 " : "-mr-0.5 ", + "w-3 h-3 rounded-full border-2 bg-white dark:bg-gray-800" + )} + style={{ + borderColor: color, + top: position, + }} + > + + )} - {left === true && - type === "str" && - !data.node.template[name].options ? ( -
- {data.node.template[name].list ? ( - { - data.node.template[name].value = t; - save(); - }} - /> - ) : data.node.template[name].multiline ? ( - { - data.node.template[name].value = t; - save(); - }} - /> - ) : ( - { - data.node.template[name].value = t; - save(); - }} - /> - )} -
- ) : left === true && type === "bool" ? ( -
- { - data.node.template[name].value = t; - setEnabled(t); - save(); - }} - /> -
- ) : left === true && type === "float" ? ( - { - data.node.template[name].value = t; - save(); - }} - /> - ) : left === true && - type === "str" && - data.node.template[name].options ? ( - (data.node.template[name].value = newValue)} - value={data.node.template[name].value ?? "Choose an option"} - > - ) : left === true && type === "code" ? ( - { - data.node.template[name].value = t; - save(); - }} - /> - ) : left === true && type === "file" ? ( - { - data.node.template[name].value = t; - }} - fileTypes={data.node.template[name].fileTypes} - suffixes={data.node.template[name].suffixes} - onFileChange={(t: string) => { - data.node.template[name].content = t; - save(); - }} - > - ) : left === true && type === "int" ? ( - { - data.node.template[name].value = t; - save(); - }} - /> - ) : left === true && type === "prompt" ? ( - { - data.node.template[name].value = t; - save(); - }} - /> - ) : ( - <> - )} - -
- ); + {left === true && + type === "str" && + !data.node.template[name].options ? ( +
+ {data.node.template[name].list ? ( + { + data.node.template[name].value = t; + save(); + }} + /> + ) : data.node.template[name].multiline ? ( + { + data.node.template[name].value = t; + save(); + }} + /> + ) : ( + { + data.node.template[name].value = t; + save(); + }} + /> + )} +
+ ) : left === true && type === "bool" ? ( +
+ { + data.node.template[name].value = t; + setEnabled(t); + save(); + }} + /> +
+ ) : left === true && type === "float" ? ( + { + data.node.template[name].value = t; + save(); + }} + /> + ) : left === true && + type === "str" && + data.node.template[name].options ? ( + (data.node.template[name].value = newValue)} + value={data.node.template[name].value ?? "Choose an option"} + > + ) : left === true && type === "code" ? ( + { + data.node.template[name].value = t; + save(); + }} + /> + ) : left === true && type === "file" ? ( + { + data.node.template[name].value = t; + }} + fileTypes={data.node.template[name].fileTypes} + suffixes={data.node.template[name].suffixes} + onFileChange={(t: string) => { + data.node.template[name].content = t; + save(); + }} + > + ) : left === true && type === "int" ? ( + { + data.node.template[name].value = t; + save(); + }} + /> + ) : left === true && type === "prompt" ? ( + { + data.node.template[name].value = t; + save(); + }} + /> + ) : ( + <> + )} + +
+ ); } diff --git a/src/frontend/src/alerts/alertDropDown/components/singleAlertComponent/index.tsx b/src/frontend/src/alerts/alertDropDown/components/singleAlertComponent/index.tsx index be168b6c3..ace9b5a0b 100644 --- a/src/frontend/src/alerts/alertDropDown/components/singleAlertComponent/index.tsx +++ b/src/frontend/src/alerts/alertDropDown/components/singleAlertComponent/index.tsx @@ -1,8 +1,8 @@ import { - XCircleIcon, - XMarkIcon, - InformationCircleIcon, - CheckCircleIcon, + XCircleIcon, + XMarkIcon, + InformationCircleIcon, + CheckCircleIcon, } from "@heroicons/react/24/outline"; import { Link } from "react-router-dom"; import { Transition } from "@headlessui/react"; @@ -10,145 +10,152 @@ import { useState } from "react"; import { SingleAlertComponentType } from "../../../../types/alerts"; export default function SingleAlert({ - dropItem, - removeAlert, + dropItem, + removeAlert, }: SingleAlertComponentType) { - const [show, setShow] = useState(true); - const type = dropItem.type; + const [show, setShow] = useState(true); + const type = dropItem.type; - return ( - - {type === "error" ? ( -
-
-
-
-

- {dropItem.title} -

- {dropItem.list ? ( -
-
    - {dropItem.list.map((item, idx) => ( -
  • {item}
  • - ))} -
-
- ) : ( - <> - )} -
-
-
- -
-
-
- ) : type === "notice" ? ( -
-
-
-
-

{dropItem.title}

-

- {dropItem.link ? ( - - Details - - ) : ( - <> - )} -

-
-
-
- -
-
-
- ) : ( -
-
-
-
-

- {dropItem.title} -

-
-
-
- -
-
-
- )} -
- ); + return ( + + {type === "error" ? ( +
+
+
+
+

+ {dropItem.title} +

+ {dropItem.list ? ( +
+
    + {dropItem.list.map((item, idx) => ( +
  • + {item} +
  • + ))} +
+
+ ) : ( + <> + )} +
+
+
+ +
+
+
+ ) : type === "notice" ? ( +
+
+
+
+

+ {dropItem.title} +

+

+ {dropItem.link ? ( + + Details + + ) : ( + <> + )} +

+
+
+
+ +
+
+
+ ) : ( +
+
+
+
+

+ {dropItem.title} +

+
+
+
+ +
+
+
+ )} +
+ ); } diff --git a/src/frontend/src/alerts/alertDropDown/index.tsx b/src/frontend/src/alerts/alertDropDown/index.tsx index 09c91c7ca..edd3bb23f 100644 --- a/src/frontend/src/alerts/alertDropDown/index.tsx +++ b/src/frontend/src/alerts/alertDropDown/index.tsx @@ -7,60 +7,60 @@ import { AlertDropdownType } from "../../types/alerts"; import { PopUpContext } from "../../contexts/popUpContext"; import { useOnClickOutside } from "../hooks/useOnClickOutside"; export default function AlertDropdown({}: AlertDropdownType) { - const { closePopUp } = useContext(PopUpContext); - const componentRef = useRef(null); + const { closePopUp } = useContext(PopUpContext); + const componentRef = useRef(null); - // Use the custom hook - useOnClickOutside(componentRef, () => { - closePopUp(); - }); + // Use the custom hook + useOnClickOutside(componentRef, () => { + closePopUp(); + }); - const { - notificationList, - clearNotificationList, - removeFromNotificationList, - } = useContext(alertContext); + const { + notificationList, + clearNotificationList, + removeFromNotificationList, + } = useContext(alertContext); - return ( -
-
- Notifications -
- - -
-
-
- {notificationList.length !== 0 ? ( - notificationList.map((alertItem, index) => ( - - )) - ) : ( -
- No new notifications -
- )} -
-
- ); + return ( +
+
+ Notifications +
+ + +
+
+
+ {notificationList.length !== 0 ? ( + notificationList.map((alertItem, index) => ( + + )) + ) : ( +
+ No new notifications +
+ )} +
+
+ ); } diff --git a/src/frontend/src/alerts/error/index.tsx b/src/frontend/src/alerts/error/index.tsx index 022ad8ba0..bcabe764f 100644 --- a/src/frontend/src/alerts/error/index.tsx +++ b/src/frontend/src/alerts/error/index.tsx @@ -4,63 +4,68 @@ import { useEffect, useState } from "react"; import { ErrorAlertType } from "../../types/alerts"; export default function ErrorAlert({ - title, - list = [], - id, - removeAlert, + title, + list = [], + id, + removeAlert, }: ErrorAlertType) { - const [show, setShow] = useState(true); - useEffect(() => { - if (show) { - setTimeout(() => { - setShow(false); - setTimeout(() => { - removeAlert(id); - }, 500); - }, 5000); - } - }, [id, removeAlert, show]); - return ( - -
{ - setShow(false); - setTimeout(() => { - removeAlert(id); - }, 500); - }} - className="rounded-md w-96 mt-6 shadow-xl bg-red-50 dark:bg-red-900 p-4 cursor-pointer" - > -
-
-
-
-

{title}

- {list.length !== 0 ? ( -
-
    - {list.map((item, index) => ( -
  • {item}
  • - ))} -
-
- ) : ( - <> - )} -
-
-
-
- ); + const [show, setShow] = useState(true); + useEffect(() => { + if (show) { + setTimeout(() => { + setShow(false); + setTimeout(() => { + removeAlert(id); + }, 500); + }, 5000); + } + }, [id, removeAlert, show]); + return ( + +
{ + setShow(false); + setTimeout(() => { + removeAlert(id); + }, 500); + }} + className="rounded-md w-96 mt-6 shadow-xl bg-red-50 dark:bg-red-900 p-4 cursor-pointer" + > +
+
+
+
+

+ {title} +

+ {list.length !== 0 ? ( +
+
    + {list.map((item, index) => ( +
  • {item}
  • + ))} +
+
+ ) : ( + <> + )} +
+
+
+
+ ); } diff --git a/src/frontend/src/alerts/hooks/useOnClickOutside/index.ts b/src/frontend/src/alerts/hooks/useOnClickOutside/index.ts index 3046d41a4..249133d96 100644 --- a/src/frontend/src/alerts/hooks/useOnClickOutside/index.ts +++ b/src/frontend/src/alerts/hooks/useOnClickOutside/index.ts @@ -1,33 +1,33 @@ import { useEffect } from "react"; export function useOnClickOutside(ref, handler) { - useEffect(() => { - const listener = (event) => { - // Do nothing if clicking ref's element or its children - if (!ref.current || ref.current.contains(event.target)) { - return; - } + useEffect(() => { + const listener = (event) => { + // Do nothing if clicking ref's element or its children + if (!ref.current || ref.current.contains(event.target)) { + return; + } - handler(event); - }; + handler(event); + }; - // Attach the listener to the document - document.addEventListener("mousedown", listener, { passive: true }); + // Attach the listener to the document + document.addEventListener("mousedown", listener, { passive: true }); - // Attach the listener to the react-flow instance - const reactFlowContainer = document.querySelector(".react-flow"); - if (reactFlowContainer) { - reactFlowContainer.addEventListener("mousedown", listener, { - passive: true, - }); - } + // Attach the listener to the react-flow instance + const reactFlowContainer = document.querySelector(".react-flow"); + if (reactFlowContainer) { + reactFlowContainer.addEventListener("mousedown", listener, { + passive: true, + }); + } - // Clean up the listener when the component is unmounted - return () => { - document.removeEventListener("mousedown", listener); - if (reactFlowContainer) { - reactFlowContainer.removeEventListener("mousedown", listener); - } - }; - }, [ref, handler]); // Rerun only if ref or handler changes + // Clean up the listener when the component is unmounted + return () => { + document.removeEventListener("mousedown", listener); + if (reactFlowContainer) { + reactFlowContainer.removeEventListener("mousedown", listener); + } + }; + }, [ref, handler]); // Rerun only if ref or handler changes } diff --git a/src/frontend/src/alerts/notice/index.tsx b/src/frontend/src/alerts/notice/index.tsx index e7e317157..1b2fb1514 100644 --- a/src/frontend/src/alerts/notice/index.tsx +++ b/src/frontend/src/alerts/notice/index.tsx @@ -5,63 +5,63 @@ import { Link } from "react-router-dom"; import { NoticeAlertType } from "../../types/alerts"; export default function NoticeAlert({ - title, - link = "", - id, - removeAlert, + title, + link = "", + id, + removeAlert, }: NoticeAlertType) { - const [show, setShow] = useState(true); - useEffect(() => { - if (show) { - setTimeout(() => { - setShow(false); - setTimeout(() => { - removeAlert(id); - }, 500); - }, 5000); - } - }, [id, removeAlert, show]); - return ( - -
{ - setShow(false); - removeAlert(id); - }} - className="rounded-md w-96 mt-6 shadow-xl bg-blue-50 dark:bg-blue-900 p-4" - > -
-
-
-
-

{title}

-

- {link !== "" ? ( - - Details - - ) : ( - <> - )} -

-
-
-
-
- ); + const [show, setShow] = useState(true); + useEffect(() => { + if (show) { + setTimeout(() => { + setShow(false); + setTimeout(() => { + removeAlert(id); + }, 500); + }, 5000); + } + }, [id, removeAlert, show]); + return ( + +
{ + setShow(false); + removeAlert(id); + }} + className="rounded-md w-96 mt-6 shadow-xl bg-blue-50 dark:bg-blue-900 p-4" + > +
+
+
+
+

{title}

+

+ {link !== "" ? ( + + Details + + ) : ( + <> + )} +

+
+
+
+
+ ); } diff --git a/src/frontend/src/alerts/success/index.tsx b/src/frontend/src/alerts/success/index.tsx index 6e82075f9..d915adfcd 100644 --- a/src/frontend/src/alerts/success/index.tsx +++ b/src/frontend/src/alerts/success/index.tsx @@ -4,50 +4,52 @@ import { useEffect, useState } from "react"; import { SuccessAlertType } from "../../types/alerts"; export default function SuccessAlert({ - title, - id, - removeAlert, + title, + id, + removeAlert, }: SuccessAlertType) { - const [show, setShow] = useState(true); - useEffect(() => { - if (show) { - setTimeout(() => { - setShow(false); - setTimeout(() => { - removeAlert(id); - }, 500); - }, 5000); - } - }, [id, removeAlert, show]); - return ( - -
{ - setShow(false); - removeAlert(id); - }} - className="rounded-md w-96 mt-6 shadow-xl bg-green-50 dark:bg-green-900 p-4" - > -
-
-
-
-

{title}

-
-
-
-
- ); + const [show, setShow] = useState(true); + useEffect(() => { + if (show) { + setTimeout(() => { + setShow(false); + setTimeout(() => { + removeAlert(id); + }, 500); + }, 5000); + } + }, [id, removeAlert, show]); + return ( + +
{ + setShow(false); + removeAlert(id); + }} + className="rounded-md w-96 mt-6 shadow-xl bg-green-50 dark:bg-green-900 p-4" + > +
+
+
+
+

+ {title} +

+
+
+
+
+ ); } diff --git a/src/frontend/src/components/CrashErrorComponent/index.tsx b/src/frontend/src/components/CrashErrorComponent/index.tsx index de3cea182..adc8909a8 100644 --- a/src/frontend/src/components/CrashErrorComponent/index.tsx +++ b/src/frontend/src/components/CrashErrorComponent/index.tsx @@ -1,33 +1,33 @@ export default function CrashErrorComponent({ error, resetErrorBoundary }) { - return ( -
-
-

- Oops! An unknown error has occurred. -

-

- Please click the 'Reset Application' button to restore the - application's state. If the error persists, please create an issue on - our GitHub page. We apologize for any inconvenience this may have - caused. -

-
- - - Create Issue - -
-
-
- ); + return ( +
+
+

+ Oops! An unknown error has occurred. +

+

+ Please click the 'Reset Application' button to restore the + application's state. If the error persists, please create an issue on + our GitHub page. We apologize for any inconvenience this may have + caused. +

+
+ + + Create Issue + +
+
+
+ ); } diff --git a/src/frontend/src/components/ExtraSidebarComponent/index.tsx b/src/frontend/src/components/ExtraSidebarComponent/index.tsx index 317f025ae..f5acd5a23 100644 --- a/src/frontend/src/components/ExtraSidebarComponent/index.tsx +++ b/src/frontend/src/components/ExtraSidebarComponent/index.tsx @@ -6,119 +6,119 @@ import { classNames } from "../../utils"; import { locationContext } from "../../contexts/locationContext"; export default function ExtraSidebar() { - const { - current, - isStackedOpen, - setIsStackedOpen, - extraNavigation, - extraComponent, - } = useContext(locationContext); - return ( - <> - - - ); + const { + current, + isStackedOpen, + setIsStackedOpen, + extraNavigation, + extraComponent, + } = useContext(locationContext); + return ( + <> + + + ); } diff --git a/src/frontend/src/components/LightTooltipComponent/index.tsx b/src/frontend/src/components/LightTooltipComponent/index.tsx index 334fc0e71..4cdc912d0 100644 --- a/src/frontend/src/components/LightTooltipComponent/index.tsx +++ b/src/frontend/src/components/LightTooltipComponent/index.tsx @@ -2,16 +2,16 @@ import { styled } from "@mui/material/styles"; import Tooltip, { TooltipProps, tooltipClasses } from "@mui/material/Tooltip"; export const LightTooltip = styled(({ className, ...props }: TooltipProps) => ( - + ))(({ theme }) => ({ - [`& .${tooltipClasses.tooltip}`]: { - backgroundColor: theme.palette.common.white, - color: "rgba(0, 0, 0, 0.87)", - boxShadow: theme.shadows[2], - fontSize: 14, - }, - [`& .${tooltipClasses.arrow}:before`]: { - color: theme.palette.common.white, - boxShadow: theme.shadows[1], - }, + [`& .${tooltipClasses.tooltip}`]: { + backgroundColor: theme.palette.common.white, + color: "rgba(0, 0, 0, 0.87)", + boxShadow: theme.shadows[2], + fontSize: 14, + }, + [`& .${tooltipClasses.arrow}:before`]: { + color: theme.palette.common.white, + boxShadow: theme.shadows[1], + }, })); diff --git a/src/frontend/src/components/TooltipComponent/index.tsx b/src/frontend/src/components/TooltipComponent/index.tsx index f0a4eb8e6..0e571b1bc 100644 --- a/src/frontend/src/components/TooltipComponent/index.tsx +++ b/src/frontend/src/components/TooltipComponent/index.tsx @@ -3,13 +3,13 @@ import { LightTooltip } from "../LightTooltipComponent"; import { TooltipComponentType } from "../../types/components"; export default function Tooltip({ - children, - title, - placement, + children, + title, + placement, }: TooltipComponentType) { - return ( - - {children} - - ); + return ( + + {children} + + ); } diff --git a/src/frontend/src/components/chatComponent/chatMessage/index.tsx b/src/frontend/src/components/chatComponent/chatMessage/index.tsx index 9e3586d23..8ca2e56e3 100644 --- a/src/frontend/src/components/chatComponent/chatMessage/index.tsx +++ b/src/frontend/src/components/chatComponent/chatMessage/index.tsx @@ -1,7 +1,7 @@ import { - ChatBubbleLeftEllipsisIcon, - ChatBubbleOvalLeftEllipsisIcon, - PlusSmallIcon, + ChatBubbleLeftEllipsisIcon, + ChatBubbleOvalLeftEllipsisIcon, + PlusSmallIcon, } from "@heroicons/react/24/outline"; import { useState } from "react"; import { ChatMessageType } from "../../../types/chat"; @@ -10,49 +10,49 @@ import Convert from "ansi-to-html"; const convert = new Convert({ newline: true }); export default function ChatMessage({ chat }: { chat: ChatMessageType }) { - const [hidden, setHidden] = useState(true); - return ( -
- {!chat.isSend ? ( -
-
- {hidden && chat.thought && chat.thought !== "" && ( -
setHidden((prev) => !prev)} - className="absolute top-2 right-2 cursor-pointer" - > - -
- )} - {chat.thought && chat.thought !== "" && !hidden && ( -
setHidden((prev) => !prev)} - style={{ backgroundColor: nodeColors["thought"] }} - className=" text-start inline-block w-full pb-3 pt-3 px-5 cursor-pointer" - dangerouslySetInnerHTML={{ - __html: convert.toHtml(chat.thought), - }} - >
- )} - {chat.thought && chat.thought !== "" && !hidden &&

} -
- {chat.message} -
-
-
- ) : ( -
-
- {chat.message} -
-
- )} -
- ); + const [hidden, setHidden] = useState(true); + return ( +
+ {!chat.isSend ? ( +
+
+ {hidden && chat.thought && chat.thought !== "" && ( +
setHidden((prev) => !prev)} + className="absolute top-2 right-2 cursor-pointer" + > + +
+ )} + {chat.thought && chat.thought !== "" && !hidden && ( +
setHidden((prev) => !prev)} + style={{ backgroundColor: nodeColors["thought"] }} + className=" text-start inline-block w-full pb-3 pt-3 px-5 cursor-pointer" + dangerouslySetInnerHTML={{ + __html: convert.toHtml(chat.thought), + }} + >
+ )} + {chat.thought && chat.thought !== "" && !hidden &&

} +
+ {chat.message} +
+
+
+ ) : ( +
+
+ {chat.message} +
+
+ )} +
+ ); } diff --git a/src/frontend/src/components/chatComponent/index.tsx b/src/frontend/src/components/chatComponent/index.tsx index dc51c0fb7..61d0f35a1 100644 --- a/src/frontend/src/components/chatComponent/index.tsx +++ b/src/frontend/src/components/chatComponent/index.tsx @@ -7,26 +7,26 @@ import ChatModal from "../../modals/chatModal"; import _ from "lodash"; export default function Chat({ flow }: ChatType) { - const [open, setOpen] = useState(false); - useEffect(() => { - const handleKeyDown = (event: KeyboardEvent) => { - if ( - (event.key === "K" || event.key === "k") && - (event.metaKey || event.ctrlKey) - ) { - event.preventDefault(); - setOpen((oldState) => !oldState); - } - }; - document.addEventListener("keydown", handleKeyDown); - return () => { - document.removeEventListener("keydown", handleKeyDown); - }; - }, []); - return ( - <> - - - - ); + const [open, setOpen] = useState(false); + useEffect(() => { + const handleKeyDown = (event: KeyboardEvent) => { + if ( + (event.key === "K" || event.key === "k") && + (event.metaKey || event.ctrlKey) + ) { + event.preventDefault(); + setOpen((oldState) => !oldState); + } + }; + document.addEventListener("keydown", handleKeyDown); + return () => { + document.removeEventListener("keydown", handleKeyDown); + }; + }, []); + return ( + <> + + + + ); } diff --git a/src/frontend/src/components/codeAreaComponent/index.tsx b/src/frontend/src/components/codeAreaComponent/index.tsx index 2da5323e8..9bf256594 100644 --- a/src/frontend/src/components/codeAreaComponent/index.tsx +++ b/src/frontend/src/components/codeAreaComponent/index.tsx @@ -6,60 +6,60 @@ import TextAreaModal from "../../modals/textAreaModal"; import { TextAreaComponentType } from "../../types/components"; export default function CodeAreaComponent({ - value, - onChange, - disabled, + value, + onChange, + disabled, }: TextAreaComponentType) { - const [myValue, setMyValue] = useState(value); - const { openPopUp } = useContext(PopUpContext); - useEffect(() => { - if (disabled) { - setMyValue(""); - onChange(""); - } - }, [disabled, onChange]); - return ( -
-
- { - openPopUp( - { - setMyValue(t); - onChange(t); - }} - /> - ); - }} - className={ - "truncate block w-full text-gray-500 px-3 py-2 rounded-md border border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" + - (disabled ? " bg-gray-200" : "") - } - > - {myValue !== "" ? myValue : "Text empty"} - - -
-
- ); + const [myValue, setMyValue] = useState(value); + const { openPopUp } = useContext(PopUpContext); + useEffect(() => { + if (disabled) { + setMyValue(""); + onChange(""); + } + }, [disabled, onChange]); + return ( +
+
+ { + openPopUp( + { + setMyValue(t); + onChange(t); + }} + /> + ); + }} + className={ + "truncate block w-full text-gray-500 px-3 py-2 rounded-md border border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" + + (disabled ? " bg-gray-200" : "") + } + > + {myValue !== "" ? myValue : "Text empty"} + + +
+
+ ); } diff --git a/src/frontend/src/components/dropdownComponent/index.tsx b/src/frontend/src/components/dropdownComponent/index.tsx index 92085d8b8..bb4cd621c 100644 --- a/src/frontend/src/components/dropdownComponent/index.tsx +++ b/src/frontend/src/components/dropdownComponent/index.tsx @@ -5,90 +5,90 @@ import { DropDownComponentType } from "../../types/components"; import { classNames } from "../../utils"; export default function Dropdown({ - value, - options, - onSelect, + value, + options, + onSelect, }: DropDownComponentType) { - let [internalValue, setInternalValue] = useState( - value === "" || !value ? "Choose an option" : value - ); - return ( - <> - { - setInternalValue(value); - onSelect(value); - }} - > - {({ open }) => ( - <> -
- - {internalValue} - - - + let [internalValue, setInternalValue] = useState( + value === "" || !value ? "Choose an option" : value + ); + return ( + <> + { + setInternalValue(value); + onSelect(value); + }} + > + {({ open }) => ( + <> +
+ + {internalValue} + + + - - - {options.map((option, id) => ( - - classNames( - active - ? "text-white bg-indigo-600 dark:bg-indigo-500" - : "text-gray-900", - "relative cursor-default select-none py-2 pl-3 pr-9 dark:text-gray-300 dark:bg-gray-800" - ) - } - value={option} - > - {({ selected, active }) => ( - <> - - {option} - + + + {options.map((option, id) => ( + + classNames( + active + ? "text-white bg-indigo-600 dark:bg-indigo-500" + : "text-gray-900", + "relative cursor-default select-none py-2 pl-3 pr-9 dark:text-gray-300 dark:bg-gray-800" + ) + } + value={option} + > + {({ selected, active }) => ( + <> + + {option} + - {selected ? ( - - - ) : null} - - )} - - ))} - - -
- - )} -
- - ); + {selected ? ( + + + ) : null} + + )} + + ))} + + +
+ + )} +
+ + ); } diff --git a/src/frontend/src/components/floatComponent/index.tsx b/src/frontend/src/components/floatComponent/index.tsx index 2752db43c..f3678b0c1 100644 --- a/src/frontend/src/components/floatComponent/index.tsx +++ b/src/frontend/src/components/floatComponent/index.tsx @@ -3,33 +3,32 @@ import { FloatComponentType } from "../../types/components"; import { TabsContext } from "../../contexts/tabsContext"; export default function FloatComponent({ - value, - onChange, - disabled, + value, + onChange, + disabled, }: FloatComponentType) { - const [myValue, setMyValue] = useState(value ?? ""); - useEffect(() => { - if (disabled) { - setMyValue(""); - onChange(""); - } - }, [disabled, onChange]); - return ( -
- { - setMyValue(e.target.value); - onChange(e.target.value); - }} - - /> -
- ); + const [myValue, setMyValue] = useState(value ?? ""); + useEffect(() => { + if (disabled) { + setMyValue(""); + onChange(""); + } + }, [disabled, onChange]); + return ( +
+ { + setMyValue(e.target.value); + onChange(e.target.value); + }} + /> +
+ ); } diff --git a/src/frontend/src/components/inputComponent/index.tsx b/src/frontend/src/components/inputComponent/index.tsx index 648458f2b..8f8f4c587 100644 --- a/src/frontend/src/components/inputComponent/index.tsx +++ b/src/frontend/src/components/inputComponent/index.tsx @@ -4,85 +4,84 @@ import { classNames } from "../../utils"; import { TabsContext } from "../../contexts/tabsContext"; export default function InputComponent({ - value, - onChange, - disabled, - password, + value, + onChange, + disabled, + password, }: InputComponentType) { - const [myValue, setMyValue] = useState(value ?? ""); - const [pwdVisible, setPwdVisible] = useState(false); - useEffect(() => { - if (disabled) { - setMyValue(""); - onChange(""); - } - }, [disabled, onChange]); - return ( -
- { - setMyValue(e.target.value); - onChange(e.target.value); - }} - /> - -
- ); + const [myValue, setMyValue] = useState(value ?? ""); + const [pwdVisible, setPwdVisible] = useState(false); + useEffect(() => { + if (disabled) { + setMyValue(""); + onChange(""); + } + }, [disabled, onChange]); + return ( +
+ { + setMyValue(e.target.value); + onChange(e.target.value); + }} + /> + +
+ ); } diff --git a/src/frontend/src/components/inputFileComponent/index.tsx b/src/frontend/src/components/inputFileComponent/index.tsx index 01a500f91..8b998c731 100644 --- a/src/frontend/src/components/inputFileComponent/index.tsx +++ b/src/frontend/src/components/inputFileComponent/index.tsx @@ -4,83 +4,83 @@ import { alertContext } from "../../contexts/alertContext"; import { FileComponentType } from "../../types/components"; export default function InputFileComponent({ - value, - onChange, - disabled, - suffixes, - fileTypes, - onFileChange, + value, + onChange, + disabled, + suffixes, + fileTypes, + onFileChange, }: FileComponentType) { - const [myValue, setMyValue] = useState(value); - const { setErrorData } = useContext(alertContext); - useEffect(() => { - if (disabled) { - setMyValue(""); - onChange(""); - onFileChange(""); - } - }, [disabled, onChange]); + const [myValue, setMyValue] = useState(value); + const { setErrorData } = useContext(alertContext); + useEffect(() => { + if (disabled) { + setMyValue(""); + onChange(""); + onFileChange(""); + } + }, [disabled, onChange]); - function attachFile(fileReadEvent: ProgressEvent) { - fileReadEvent.preventDefault(); - const file = fileReadEvent.target.result; - onFileChange(file as string); - } + function attachFile(fileReadEvent: ProgressEvent) { + fileReadEvent.preventDefault(); + const file = fileReadEvent.target.result; + onFileChange(file as string); + } - function checkFileType(fileName: string): boolean { - for (let index = 0; index < suffixes.length; index++) { - if (fileName.endsWith(suffixes[index])) { - return true; - } - } - return false; - } + function checkFileType(fileName: string): boolean { + for (let index = 0; index < suffixes.length; index++) { + if (fileName.endsWith(suffixes[index])) { + return true; + } + } + return false; + } - const handleButtonClick = () => { - const input = document.createElement("input"); - input.type = "file"; - input.accept = suffixes.join(","); - input.style.display = "none"; - input.multiple = false; - input.onchange = (e: Event) => { - const file = (e.target as HTMLInputElement).files?.[0]; - const fileData = new FileReader(); - fileData.onload = attachFile; - if (file && checkFileType(file.name)) { - fileData.readAsDataURL(file); - setMyValue(file.name); - onChange(file.name); - } else { - setErrorData({ - title: - "Please select a valid file. Only files this files are allowed:", - list: fileTypes, - }); - } - }; - input.click(); - }; + const handleButtonClick = () => { + const input = document.createElement("input"); + input.type = "file"; + input.accept = suffixes.join(","); + input.style.display = "none"; + input.multiple = false; + input.onchange = (e: Event) => { + const file = (e.target as HTMLInputElement).files?.[0]; + const fileData = new FileReader(); + fileData.onload = attachFile; + if (file && checkFileType(file.name)) { + fileData.readAsDataURL(file); + setMyValue(file.name); + onChange(file.name); + } else { + setErrorData({ + title: + "Please select a valid file. Only files this files are allowed:", + list: fileTypes, + }); + } + }; + input.click(); + }; - return ( -
-
- - {myValue !== "" ? myValue : "No file"} - - -
-
- ); + return ( +
+
+ + {myValue !== "" ? myValue : "No file"} + + +
+
+ ); } diff --git a/src/frontend/src/components/inputListComponent/index.tsx b/src/frontend/src/components/inputListComponent/index.tsx index 01f783ad6..ea47af8f9 100644 --- a/src/frontend/src/components/inputListComponent/index.tsx +++ b/src/frontend/src/components/inputListComponent/index.tsx @@ -6,72 +6,72 @@ import { TabsContext } from "../../contexts/tabsContext"; import _ from "lodash"; export default function InputListComponent({ - value, - onChange, - disabled, + value, + onChange, + disabled, }: InputListComponentType) { - const [inputList, setInputList] = useState(value ?? [""]); - useEffect(() => { - if (disabled) { - setInputList([""]); - onChange([""]); - } - }, [disabled, onChange]); - return ( -
- {inputList.map((i, idx) => ( -
- { - setInputList((old) => { - let newInputList = _.cloneDeep(old); - newInputList[idx] = e.target.value; - return newInputList; - }); - onChange(inputList); - }} - /> - {idx === inputList.length - 1 ? ( - - ) : ( - - )} -
- ))} -
- ); + const [inputList, setInputList] = useState(value ?? [""]); + useEffect(() => { + if (disabled) { + setInputList([""]); + onChange([""]); + } + }, [disabled, onChange]); + return ( +
+ {inputList.map((i, idx) => ( +
+ { + setInputList((old) => { + let newInputList = _.cloneDeep(old); + newInputList[idx] = e.target.value; + return newInputList; + }); + onChange(inputList); + }} + /> + {idx === inputList.length - 1 ? ( + + ) : ( + + )} +
+ ))} +
+ ); } diff --git a/src/frontend/src/components/intComponent/index.tsx b/src/frontend/src/components/intComponent/index.tsx index b2713b369..80f687924 100644 --- a/src/frontend/src/components/intComponent/index.tsx +++ b/src/frontend/src/components/intComponent/index.tsx @@ -3,50 +3,48 @@ import { FloatComponentType } from "../../types/components"; import { TabsContext } from "../../contexts/tabsContext"; export default function IntComponent({ - value, - onChange, - disabled, + value, + onChange, + disabled, }: FloatComponentType) { - const [myValue, setMyValue] = useState(value ?? ""); - useEffect(() => { - if (disabled) { - setMyValue(""); - onChange(""); - } - }, [disabled, onChange]); - return ( -
- { - if ( - event.key !== "Backspace" && - event.key !== "Enter" && - event.key !== "Delete" && - event.key !== "ArrowLeft" && - event.key !== "ArrowRight" && - !/^[-]?\d*$/.test(event.key) - ) { - event.preventDefault(); - } - }} - type="number" - value={myValue} - className={ - "block w-full form-input dark:bg-gray-900 arrow-hide dark:border-gray-600 rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" + - (disabled ? " bg-gray-200 dark:bg-gray-700" : "") - } - placeholder="Type a integer number" - onChange={(e) => { - setMyValue(e.target.value); - onChange(e.target.value); - }} - - /> - -
- ); + const [myValue, setMyValue] = useState(value ?? ""); + useEffect(() => { + if (disabled) { + setMyValue(""); + onChange(""); + } + }, [disabled, onChange]); + return ( +
+ { + if ( + event.key !== "Backspace" && + event.key !== "Enter" && + event.key !== "Delete" && + event.key !== "ArrowLeft" && + event.key !== "ArrowRight" && + !/^[-]?\d*$/.test(event.key) + ) { + event.preventDefault(); + } + }} + type="number" + value={myValue} + className={ + "block w-full form-input dark:bg-gray-900 arrow-hide dark:border-gray-600 rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" + + (disabled ? " bg-gray-200 dark:bg-gray-700" : "") + } + placeholder="Type a integer number" + onChange={(e) => { + setMyValue(e.target.value); + onChange(e.target.value); + }} + /> +
+ ); } diff --git a/src/frontend/src/components/loadingComponent/index.tsx b/src/frontend/src/components/loadingComponent/index.tsx index 43d6d9d75..42ad18c1e 100644 --- a/src/frontend/src/components/loadingComponent/index.tsx +++ b/src/frontend/src/components/loadingComponent/index.tsx @@ -1,28 +1,28 @@ type LoadingComponentProps = { - remSize: number; + remSize: number; }; export default function LoadingComponent({ remSize }: LoadingComponentProps) { - return ( -
- -

- Loading... -
- ); + return ( +
+ +

+ Loading... +
+ ); } diff --git a/src/frontend/src/components/promptComponent/index.tsx b/src/frontend/src/components/promptComponent/index.tsx index 842e5e7d8..6182bd075 100644 --- a/src/frontend/src/components/promptComponent/index.tsx +++ b/src/frontend/src/components/promptComponent/index.tsx @@ -7,60 +7,60 @@ import { TextAreaComponentType } from "../../types/components"; import PromptAreaModal from "../../modals/promptModal"; export default function PromptAreaComponent({ - value, - onChange, - disabled, + value, + onChange, + disabled, }: TextAreaComponentType) { - const [myValue, setMyValue] = useState(value); - const { openPopUp } = useContext(PopUpContext); - useEffect(() => { - if (disabled) { - setMyValue(""); - onChange(""); - } - }, [disabled, onChange]); - return ( -
-
- { - openPopUp( - { - setMyValue(t); - onChange(t); - }} - /> - ); - }} - className={ - "truncate block w-full text-gray-500 px-3 py-2 rounded-md border border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" + - (disabled ? " bg-gray-200" : "") - } - > - {myValue !== "" ? myValue : "Text empty"} - - -
-
- ); + const [myValue, setMyValue] = useState(value); + const { openPopUp } = useContext(PopUpContext); + useEffect(() => { + if (disabled) { + setMyValue(""); + onChange(""); + } + }, [disabled, onChange]); + return ( +
+
+ { + openPopUp( + { + setMyValue(t); + onChange(t); + }} + /> + ); + }} + className={ + "truncate block w-full text-gray-500 px-3 py-2 rounded-md border border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" + + (disabled ? " bg-gray-200" : "") + } + > + {myValue !== "" ? myValue : "Text empty"} + + +
+
+ ); } diff --git a/src/frontend/src/components/textAreaComponent/index.tsx b/src/frontend/src/components/textAreaComponent/index.tsx index 3737e02f0..a2fbad22a 100644 --- a/src/frontend/src/components/textAreaComponent/index.tsx +++ b/src/frontend/src/components/textAreaComponent/index.tsx @@ -4,7 +4,11 @@ import { PopUpContext } from "../../contexts/popUpContext"; import TextAreaModal from "../../modals/textAreaModal"; import { TextAreaComponentType } from "../../types/components"; -export default function TextAreaComponent({ value, onChange, disabled }:TextAreaComponentType) { +export default function TextAreaComponent({ + value, + onChange, + disabled, +}: TextAreaComponentType) { const [myValue, setMyValue] = useState(value); const { openPopUp } = useContext(PopUpContext); useEffect(() => { @@ -16,16 +20,39 @@ export default function TextAreaComponent({ value, onChange, disabled }:TextArea return (
- {openPopUp( {setMyValue(t); onChange(t);}}/>)}} + { + openPopUp( + { + setMyValue(t); + onChange(t); + }} + /> + ); + }} className={ "truncate block w-full text-gray-500 dark:text-gray-100 px-3 py-2 rounded-md border border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" + (disabled ? " bg-gray-200" : "") } > - {myValue !== "" ? myValue : 'Text empty'} + {myValue !== "" ? myValue : "Text empty"} -
diff --git a/src/frontend/src/components/toggleComponent/index.tsx b/src/frontend/src/components/toggleComponent/index.tsx index eed5bc278..f7140bdee 100644 --- a/src/frontend/src/components/toggleComponent/index.tsx +++ b/src/frontend/src/components/toggleComponent/index.tsx @@ -4,59 +4,57 @@ import { useEffect } from "react"; import { ToggleComponentType } from "../../types/components"; export default function ToggleComponent({ - enabled, - setEnabled, - disabled, + enabled, + setEnabled, + disabled, }: ToggleComponentType) { - useEffect(() => { - if (disabled) { - setEnabled(false); - } - }, [disabled, setEnabled]); - return ( -
- { - setEnabled(x); - }} - className={classNames( - enabled ? 'bg-indigo-600' : 'bg-gray-200', - 'relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2' - )} - > - Use setting - - - - - -
- ); + useEffect(() => { + if (disabled) { + setEnabled(false); + } + }, [disabled, setEnabled]); + return ( +
+ { + setEnabled(x); + }} + className={classNames( + enabled ? "bg-indigo-600" : "bg-gray-200", + "relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2" + )} + > + Use setting + + + + + +
+ ); } diff --git a/src/frontend/src/contexts/alertContext.tsx b/src/frontend/src/contexts/alertContext.tsx index ef18ade39..f85f858de 100644 --- a/src/frontend/src/contexts/alertContext.tsx +++ b/src/frontend/src/contexts/alertContext.tsx @@ -5,161 +5,161 @@ import _ from "lodash"; //types for alertContextType type alertContextType = { - errorData: { title: string; list?: Array }; - setErrorData: (newState: { title: string; list?: Array }) => void; - errorOpen: boolean; - setErrorOpen: (newState: boolean) => void; - noticeData: { title: string; link?: string }; - setNoticeData: (newState: { title: string; link?: string }) => void; - noticeOpen: boolean; - setNoticeOpen: (newState: boolean) => void; - successData: { title: string }; - setSuccessData: (newState: { title: string }) => void; - successOpen: boolean; - setSuccessOpen: (newState: boolean) => void; - notificationCenter: boolean; - setNotificationCenter: (newState: boolean) => void; - notificationList: Array; - pushNotificationList: (Object: AlertItemType) => void; - clearNotificationList: () => void; - removeFromNotificationList: (index: string) => void; + errorData: { title: string; list?: Array }; + setErrorData: (newState: { title: string; list?: Array }) => void; + errorOpen: boolean; + setErrorOpen: (newState: boolean) => void; + noticeData: { title: string; link?: string }; + setNoticeData: (newState: { title: string; link?: string }) => void; + noticeOpen: boolean; + setNoticeOpen: (newState: boolean) => void; + successData: { title: string }; + setSuccessData: (newState: { title: string }) => void; + successOpen: boolean; + setSuccessOpen: (newState: boolean) => void; + notificationCenter: boolean; + setNotificationCenter: (newState: boolean) => void; + notificationList: Array; + pushNotificationList: (Object: AlertItemType) => void; + clearNotificationList: () => void; + removeFromNotificationList: (index: string) => void; }; //initial values to alertContextType const initialValue: alertContextType = { - errorData: { title: "", list: [] }, - setErrorData: () => {}, - errorOpen: false, - setErrorOpen: () => {}, - noticeData: { title: "", link: "" }, - setNoticeData: () => {}, - noticeOpen: false, - setNoticeOpen: () => {}, - successData: { title: "" }, - setSuccessData: () => {}, - successOpen: false, - setSuccessOpen: () => {}, - notificationCenter: false, - setNotificationCenter: () => {}, - notificationList: [], - pushNotificationList: () => {}, - clearNotificationList: () => {}, - removeFromNotificationList: () => {}, + errorData: { title: "", list: [] }, + setErrorData: () => {}, + errorOpen: false, + setErrorOpen: () => {}, + noticeData: { title: "", link: "" }, + setNoticeData: () => {}, + noticeOpen: false, + setNoticeOpen: () => {}, + successData: { title: "" }, + setSuccessData: () => {}, + successOpen: false, + setSuccessOpen: () => {}, + notificationCenter: false, + setNotificationCenter: () => {}, + notificationList: [], + pushNotificationList: () => {}, + clearNotificationList: () => {}, + removeFromNotificationList: () => {}, }; export const alertContext = createContext(initialValue); export function AlertProvider({ children }: { children: ReactNode }) { - const [errorData, setErrorDataState] = useState<{ - title: string; - list?: Array; - }>({ title: "", list: [] }); - const [errorOpen, setErrorOpen] = useState(false); - const [noticeData, setNoticeDataState] = useState<{ - title: string; - link?: string; - }>({ title: "", link: "" }); - const [noticeOpen, setNoticeOpen] = useState(false); - const [successData, setSuccessDataState] = useState<{ title: string }>({ - title: "", - }); - const [successOpen, setSuccessOpen] = useState(false); - const [notificationCenter, setNotificationCenter] = useState(false); - const [notificationList, setNotificationList] = useState([]); - const pushNotificationList = (notification: AlertItemType) => { - setNotificationList((old) => { - let newNotificationList = _.cloneDeep(old); - newNotificationList.unshift(notification); - return newNotificationList; - }); - }; - /** - * Sets the error data state, opens the error dialog and pushes the new error notification to the notification list - * @param newState An object containing the new error data, including title and optional list of error messages - */ - function setErrorData(newState: { title: string; list?: Array }) { - setErrorDataState(newState); - setErrorOpen(true); - if (newState.title) { - setNotificationCenter(true); - pushNotificationList({ - type: "error", - title: newState.title, - list: newState.list, - id: _.uniqueId(), - }); - } - } - /** - * Sets the state of the notice data and opens the notice modal, also adds a new notice to the notification center if the title is defined. - * @param newState An object containing the title of the notice and optionally a link. - */ - function setNoticeData(newState: { title: string; link?: string }) { - setNoticeDataState(newState); - setNoticeOpen(true); - if (newState.title) { - // Add new notice to notification center - setNotificationCenter(true); - pushNotificationList({ - type: "notice", - title: newState.title, - link: newState.link, - id: _.uniqueId(), - }); - } - } - /** - * Update the success data state and show a success alert notification. - * @param newState - A state object with a "title" property to set in the success data state. - */ - function setSuccessData(newState: { title: string }) { - setSuccessDataState(newState); // update the success data state with the provided new state - setSuccessOpen(true); // open the success alert + const [errorData, setErrorDataState] = useState<{ + title: string; + list?: Array; + }>({ title: "", list: [] }); + const [errorOpen, setErrorOpen] = useState(false); + const [noticeData, setNoticeDataState] = useState<{ + title: string; + link?: string; + }>({ title: "", link: "" }); + const [noticeOpen, setNoticeOpen] = useState(false); + const [successData, setSuccessDataState] = useState<{ title: string }>({ + title: "", + }); + const [successOpen, setSuccessOpen] = useState(false); + const [notificationCenter, setNotificationCenter] = useState(false); + const [notificationList, setNotificationList] = useState([]); + const pushNotificationList = (notification: AlertItemType) => { + setNotificationList((old) => { + let newNotificationList = _.cloneDeep(old); + newNotificationList.unshift(notification); + return newNotificationList; + }); + }; + /** + * Sets the error data state, opens the error dialog and pushes the new error notification to the notification list + * @param newState An object containing the new error data, including title and optional list of error messages + */ + function setErrorData(newState: { title: string; list?: Array }) { + setErrorDataState(newState); + setErrorOpen(true); + if (newState.title) { + setNotificationCenter(true); + pushNotificationList({ + type: "error", + title: newState.title, + list: newState.list, + id: _.uniqueId(), + }); + } + } + /** + * Sets the state of the notice data and opens the notice modal, also adds a new notice to the notification center if the title is defined. + * @param newState An object containing the title of the notice and optionally a link. + */ + function setNoticeData(newState: { title: string; link?: string }) { + setNoticeDataState(newState); + setNoticeOpen(true); + if (newState.title) { + // Add new notice to notification center + setNotificationCenter(true); + pushNotificationList({ + type: "notice", + title: newState.title, + link: newState.link, + id: _.uniqueId(), + }); + } + } + /** + * Update the success data state and show a success alert notification. + * @param newState - A state object with a "title" property to set in the success data state. + */ + function setSuccessData(newState: { title: string }) { + setSuccessDataState(newState); // update the success data state with the provided new state + setSuccessOpen(true); // open the success alert - // If the new state has a "title" property, add a new success notification to the list - if (newState.title) { - setNotificationCenter(true); // show the notification center - pushNotificationList({ - // add the new notification to the list - type: "success", - title: newState.title, - id: _.uniqueId(), - }); - } - } - function clearNotificationList() { - setNotificationList([]); - } - function removeFromNotificationList(index: string) { - // set the notification list to a new array that filters out the alert with the matching id - setNotificationList((prevAlertsList) => - prevAlertsList.filter((alert) => alert.id !== index) - ); - } - return ( - - {children} - - ); + // If the new state has a "title" property, add a new success notification to the list + if (newState.title) { + setNotificationCenter(true); // show the notification center + pushNotificationList({ + // add the new notification to the list + type: "success", + title: newState.title, + id: _.uniqueId(), + }); + } + } + function clearNotificationList() { + setNotificationList([]); + } + function removeFromNotificationList(index: string) { + // set the notification list to a new array that filters out the alert with the matching id + setNotificationList((prevAlertsList) => + prevAlertsList.filter((alert) => alert.id !== index) + ); + } + return ( + + {children} + + ); } diff --git a/src/frontend/src/contexts/darkContext.tsx b/src/frontend/src/contexts/darkContext.tsx index c383fb1e3..f612fe381 100644 --- a/src/frontend/src/contexts/darkContext.tsx +++ b/src/frontend/src/contexts/darkContext.tsx @@ -1,34 +1,34 @@ import { createContext, useEffect, useState } from "react"; type darkContextType = { - dark: {}; - setDark: (newState: {}) => void; + dark: {}; + setDark: (newState: {}) => void; }; const initialValue = { - dark: {}, - setDark: () => {}, + dark: {}, + setDark: () => {}, }; export const darkContext = createContext(initialValue); export function DarkProvider({ children }) { - const [dark, setDark] = useState(false); - useEffect(() => { - if (dark) { - document.getElementById("body").classList.add("dark"); - } else { - document.getElementById("body").classList.remove("dark"); - } - }, [dark]); - return ( - - {children} - - ); + const [dark, setDark] = useState(false); + useEffect(() => { + if (dark) { + document.getElementById("body").classList.add("dark"); + } else { + document.getElementById("body").classList.remove("dark"); + } + }, [dark]); + return ( + + {children} + + ); } diff --git a/src/frontend/src/contexts/index.tsx b/src/frontend/src/contexts/index.tsx index bef4298e9..ab199368e 100644 --- a/src/frontend/src/contexts/index.tsx +++ b/src/frontend/src/contexts/index.tsx @@ -7,20 +7,20 @@ import { TabsProvider } from "./tabsContext"; import { TypesProvider } from "./typesContext"; export default function ContextWrapper({ children }: { children: ReactNode }) { - //element to wrap all context - return ( - <> - - - - - - {children} - - - - - - - ); + //element to wrap all context + return ( + <> + + + + + + {children} + + + + + + + ); } diff --git a/src/frontend/src/contexts/locationContext.tsx b/src/frontend/src/contexts/locationContext.tsx index a73db24fe..474062d69 100644 --- a/src/frontend/src/contexts/locationContext.tsx +++ b/src/frontend/src/contexts/locationContext.tsx @@ -2,78 +2,78 @@ import { createContext, ReactNode, useState } from "react"; //types for location context type locationContextType = { - current: Array; - setCurrent: (newState: Array) => void; - isStackedOpen: boolean; - setIsStackedOpen: (newState: boolean) => void; - showSideBar: boolean; - setShowSideBar: (newState: boolean) => void; - extraNavigation: { - title: string; - options?: Array<{ - name: string; - href: string; - icon: any; - children?: Array; - }>; - }; - setExtraNavigation: (newState: { - title: string; - options?: Array<{ - name: string; - href: string; - icon: any; - children?: Array; - }>; - }) => void; - extraComponent: any; - setExtraComponent: (newState: any) => void; + current: Array; + setCurrent: (newState: Array) => void; + isStackedOpen: boolean; + setIsStackedOpen: (newState: boolean) => void; + showSideBar: boolean; + setShowSideBar: (newState: boolean) => void; + extraNavigation: { + title: string; + options?: Array<{ + name: string; + href: string; + icon: any; + children?: Array; + }>; + }; + setExtraNavigation: (newState: { + title: string; + options?: Array<{ + name: string; + href: string; + icon: any; + children?: Array; + }>; + }) => void; + extraComponent: any; + setExtraComponent: (newState: any) => void; }; //initial value for location context const initialValue = { - //actual - current: window.location.pathname.replace(/\/$/g, "").split("/"), - isStackedOpen: - window.innerWidth > 1024 && window.location.pathname.split("/")[1] - ? true - : false, - setCurrent: () => {}, - setIsStackedOpen: () => {}, - showSideBar: window.location.pathname.split("/")[1] ? true : false, - setShowSideBar: () => {}, - extraNavigation: { title: "" }, - setExtraNavigation: () => {}, - extraComponent: <>, - setExtraComponent: () => {}, + //actual + current: window.location.pathname.replace(/\/$/g, "").split("/"), + isStackedOpen: + window.innerWidth > 1024 && window.location.pathname.split("/")[1] + ? true + : false, + setCurrent: () => {}, + setIsStackedOpen: () => {}, + showSideBar: window.location.pathname.split("/")[1] ? true : false, + setShowSideBar: () => {}, + extraNavigation: { title: "" }, + setExtraNavigation: () => {}, + extraComponent: <>, + setExtraComponent: () => {}, }; export const locationContext = createContext(initialValue); export function LocationProvider({ children }: { children: ReactNode }) { - const [current, setCurrent] = useState(initialValue.current); - const [isStackedOpen, setIsStackedOpen] = useState( - initialValue.isStackedOpen - ); - const [showSideBar, setShowSideBar] = useState(initialValue.showSideBar); - const [extraNavigation, setExtraNavigation] = useState({ title: "" }); - const [extraComponent, setExtraComponent] = useState(<>); - return ( - - {children} - - ); + const [current, setCurrent] = useState(initialValue.current); + const [isStackedOpen, setIsStackedOpen] = useState( + initialValue.isStackedOpen + ); + const [showSideBar, setShowSideBar] = useState(initialValue.showSideBar); + const [extraNavigation, setExtraNavigation] = useState({ title: "" }); + const [extraComponent, setExtraComponent] = useState(<>); + return ( + + {children} + + ); } diff --git a/src/frontend/src/contexts/popUpContext.tsx b/src/frontend/src/contexts/popUpContext.tsx index b8c47dea2..371aeefce 100644 --- a/src/frontend/src/contexts/popUpContext.tsx +++ b/src/frontend/src/contexts/popUpContext.tsx @@ -3,31 +3,31 @@ import React, { useState } from "react"; // context to set JSX element on the DOM export const PopUpContext = createContext({ - openPopUp: (popUpElement: JSX.Element) => {}, - closePopUp: () => {}, + openPopUp: (popUpElement: JSX.Element) => {}, + closePopUp: () => {}, }); interface PopUpProviderProps { - children: React.ReactNode; + children: React.ReactNode; } const PopUpProvider = ({ children }: PopUpProviderProps) => { - const [popUpElements, setPopUpElements] = useState([]); + const [popUpElements, setPopUpElements] = useState([]); - const openPopUp = (element: JSX.Element) => { - setPopUpElements((prevPopUps) => [element, ...prevPopUps]); - }; + const openPopUp = (element: JSX.Element) => { + setPopUpElements((prevPopUps) => [element, ...prevPopUps]); + }; - const closePopUp = () => { - setPopUpElements((prevPopUps) => prevPopUps.slice(1)); - }; + const closePopUp = () => { + setPopUpElements((prevPopUps) => prevPopUps.slice(1)); + }; - return ( - - {children} - {popUpElements[0]} - - ); + return ( + + {children} + {popUpElements[0]} + + ); }; export default PopUpProvider; diff --git a/src/frontend/src/contexts/tabsContext.tsx b/src/frontend/src/contexts/tabsContext.tsx index 997e563eb..6db425599 100644 --- a/src/frontend/src/contexts/tabsContext.tsx +++ b/src/frontend/src/contexts/tabsContext.tsx @@ -1,10 +1,10 @@ import { - createContext, - useEffect, - useState, - useRef, - ReactNode, - useContext, + createContext, + useEffect, + useState, + useRef, + ReactNode, + useContext, } from "react"; import { FlowType, NodeType } from "../types/flow"; import { LangFlowState, TabsContextType } from "../types/tabs"; @@ -16,328 +16,332 @@ import { v4 as uuidv4 } from "uuid"; import { addEdge } from "reactflow"; const TabsContextInitialValue: TabsContextType = { - save: () => {}, - tabIndex: 0, - setTabIndex: (index: number) => {}, - flows: [], - removeFlow: (id: string) => {}, - addFlow: (flowData?: any) => {}, - updateFlow: (newFlow: FlowType) => {}, - incrementNodeId: () => uuidv4(), - downloadFlow: (flow: FlowType) => {}, - uploadFlow: () => {}, - hardReset: () => {}, - disableCopyPaste:false, - setDisableCopyPaste:(state:boolean)=>{}, - getNodeId: () => "", - paste: (selection: {nodes: any, edges: any}, position: {x: number, y: number}) => {}, + save: () => {}, + tabIndex: 0, + setTabIndex: (index: number) => {}, + flows: [], + removeFlow: (id: string) => {}, + addFlow: (flowData?: any) => {}, + updateFlow: (newFlow: FlowType) => {}, + incrementNodeId: () => uuidv4(), + downloadFlow: (flow: FlowType) => {}, + uploadFlow: () => {}, + hardReset: () => {}, + disableCopyPaste: false, + setDisableCopyPaste: (state: boolean) => {}, + getNodeId: () => "", + paste: ( + selection: { nodes: any; edges: any }, + position: { x: number; y: number } + ) => {}, }; export const TabsContext = createContext( - TabsContextInitialValue + TabsContextInitialValue ); export function TabsProvider({ children }: { children: ReactNode }) { - const { setNoticeData } = useContext(alertContext); - const [tabIndex, setTabIndex] = useState(0); - const [flows, setFlows] = useState>([]); - const [id, setId] = useState(uuidv4()); - const { templates, reactFlowInstance } = useContext(typesContext); + const { setNoticeData } = useContext(alertContext); + const [tabIndex, setTabIndex] = useState(0); + const [flows, setFlows] = useState>([]); + const [id, setId] = useState(uuidv4()); + const { templates, reactFlowInstance } = useContext(typesContext); - const newNodeId = useRef(uuidv4()); - function incrementNodeId() { - newNodeId.current = uuidv4(); - return newNodeId.current; - } - function save() { - let Saveflows = [...flows]; - if (Saveflows.length !== 0) - Saveflows.forEach((flow) => { - if(flow.data && flow.data?.nodes) flow.data?.nodes.forEach((node) => { - console.log(node.data.type) - Object.keys(node.data.node.template).forEach((key) => { - console.log(node.data.node.template[key].type) - if(node.data.node.template[key].type==="file"){ - console.log(node.data.node.template[key]) - node.data.node.template[key].content = ""; - } - }) - }) - }) - window.localStorage.setItem( - "tabsData", - JSON.stringify({ tabIndex, flows:Saveflows, id}) - ); - } - useEffect(() => { - //save tabs locally - save(); - }, [flows, id, tabIndex, newNodeId]); + const newNodeId = useRef(uuidv4()); + function incrementNodeId() { + newNodeId.current = uuidv4(); + return newNodeId.current; + } + function save() { + let Saveflows = [...flows]; + if (Saveflows.length !== 0) + Saveflows.forEach((flow) => { + if (flow.data && flow.data?.nodes) + flow.data?.nodes.forEach((node) => { + console.log(node.data.type); + Object.keys(node.data.node.template).forEach((key) => { + console.log(node.data.node.template[key].type); + if (node.data.node.template[key].type === "file") { + console.log(node.data.node.template[key]); + node.data.node.template[key].content = ""; + } + }); + }); + }); + window.localStorage.setItem( + "tabsData", + JSON.stringify({ tabIndex, flows: Saveflows, id }) + ); + } + useEffect(() => { + //save tabs locally + save(); + }, [flows, id, tabIndex, newNodeId]); - useEffect(() => { - //get tabs locally saved - let cookie = window.localStorage.getItem("tabsData"); - if (cookie && Object.keys(templates).length > 0) { - let cookieObject: LangFlowState = JSON.parse(cookie); - cookieObject.flows.forEach((flow) => { - flow.data.nodes.forEach((node) => { - if (Object.keys(templates[node.data.type]["template"]).length > 0) { - node.data.node.template = updateTemplate( - templates[node.data.type][ - "template" - ] as unknown as APITemplateType, + useEffect(() => { + //get tabs locally saved + let cookie = window.localStorage.getItem("tabsData"); + if (cookie && Object.keys(templates).length > 0) { + let cookieObject: LangFlowState = JSON.parse(cookie); + cookieObject.flows.forEach((flow) => { + flow.data.nodes.forEach((node) => { + if (Object.keys(templates[node.data.type]["template"]).length > 0) { + node.data.node.template = updateTemplate( + templates[node.data.type][ + "template" + ] as unknown as APITemplateType, - node.data.node.template as APITemplateType - ); - } - }); - }); - setTabIndex(cookieObject.tabIndex); - setFlows(cookieObject.flows); - setId(cookieObject.id); - } - }, [templates]); + node.data.node.template as APITemplateType + ); + } + }); + }); + setTabIndex(cookieObject.tabIndex); + setFlows(cookieObject.flows); + setId(cookieObject.id); + } + }, [templates]); - function hardReset() { - newNodeId.current = uuidv4(); - setTabIndex(0); - setFlows([]); - setId(uuidv4()); - } + function hardReset() { + newNodeId.current = uuidv4(); + setTabIndex(0); + setFlows([]); + setId(uuidv4()); + } - /** - * Downloads the current flow as a JSON file - */ - function downloadFlow(flow: FlowType) { - // create a data URI with the current flow data - const jsonString = `data:text/json;chatset=utf-8,${encodeURIComponent( - JSON.stringify(flow) - )}`; + /** + * Downloads the current flow as a JSON file + */ + function downloadFlow(flow: FlowType) { + // create a data URI with the current flow data + const jsonString = `data:text/json;chatset=utf-8,${encodeURIComponent( + JSON.stringify(flow) + )}`; - // create a link element and set its properties - const link = document.createElement("a"); - link.href = jsonString; - link.download = `${flows[tabIndex].name}.json`; + // create a link element and set its properties + const link = document.createElement("a"); + link.href = jsonString; + link.download = `${flows[tabIndex].name}.json`; - // simulate a click on the link element to trigger the download - link.click(); - setNoticeData({ - title: "Warning: Critical data,JSON file may including API keys.", - }); - } + // simulate a click on the link element to trigger the download + link.click(); + setNoticeData({ + title: "Warning: Critical data,JSON file may including API keys.", + }); + } - function getNodeId() { - return `dndnode_` + incrementNodeId(); - } + function getNodeId() { + return `dndnode_` + incrementNodeId(); + } - /** - * Creates a file input and listens to a change event to upload a JSON flow file. - * If the file type is application/json, the file is read and parsed into a JSON object. - * The resulting JSON object is passed to the addFlow function. - */ - function uploadFlow() { - // create a file input - const input = document.createElement("input"); - input.type = "file"; - // add a change event listener to the file input - input.onchange = (e: Event) => { - // check if the file type is application/json - if ((e.target as HTMLInputElement).files[0].type === "application/json") { - // get the file from the file input - const file = (e.target as HTMLInputElement).files[0]; - // read the file as text - file.text().then((text) => { - // parse the text into a JSON object - let flow: FlowType = JSON.parse(text); + /** + * Creates a file input and listens to a change event to upload a JSON flow file. + * If the file type is application/json, the file is read and parsed into a JSON object. + * The resulting JSON object is passed to the addFlow function. + */ + function uploadFlow() { + // create a file input + const input = document.createElement("input"); + input.type = "file"; + // add a change event listener to the file input + input.onchange = (e: Event) => { + // check if the file type is application/json + if ((e.target as HTMLInputElement).files[0].type === "application/json") { + // get the file from the file input + const file = (e.target as HTMLInputElement).files[0]; + // read the file as text + file.text().then((text) => { + // parse the text into a JSON object + let flow: FlowType = JSON.parse(text); - addFlow(flow); - }); - } - }; - // trigger the file input click event to open the file dialog - input.click(); - } - /** - * Removes a flow from an array of flows based on its id. - * Updates the state of flows and tabIndex using setFlows and setTabIndex hooks. - * @param {string} id - The id of the flow to remove. - */ - function removeFlow(id: string) { - setFlows((prevState) => { - const newFlows = [...prevState]; - const index = newFlows.findIndex((flow) => flow.id === id); - if (index >= 0) { - if (index === tabIndex) { - setTabIndex(flows.length - 2); - newFlows.splice(index, 1); - } else { - let flowId = flows[tabIndex].id; - newFlows.splice(index, 1); - setTabIndex(newFlows.findIndex((flow) => flow.id === flowId)); - } - } - return newFlows; - }); - } - /** - * Add a new flow to the list of flows. - * @param flow Optional flow to add. - */ + addFlow(flow); + }); + } + }; + // trigger the file input click event to open the file dialog + input.click(); + } + /** + * Removes a flow from an array of flows based on its id. + * Updates the state of flows and tabIndex using setFlows and setTabIndex hooks. + * @param {string} id - The id of the flow to remove. + */ + function removeFlow(id: string) { + setFlows((prevState) => { + const newFlows = [...prevState]; + const index = newFlows.findIndex((flow) => flow.id === id); + if (index >= 0) { + if (index === tabIndex) { + setTabIndex(flows.length - 2); + newFlows.splice(index, 1); + } else { + let flowId = flows[tabIndex].id; + newFlows.splice(index, 1); + setTabIndex(newFlows.findIndex((flow) => flow.id === flowId)); + } + } + return newFlows; + }); + } + /** + * Add a new flow to the list of flows. + * @param flow Optional flow to add. + */ - function paste(selectionInstance, position){ - let minimumX = Infinity; - let minimumY = Infinity; - let idsMap = {}; - let nodes = reactFlowInstance.getNodes(); - let edges = reactFlowInstance.getEdges(); - selectionInstance.nodes.forEach((n) => { - if (n.position.y < minimumY) { - minimumY = n.position.y; - } - if (n.position.x < minimumX) { - minimumX = n.position.x; - } - }); + function paste(selectionInstance, position) { + let minimumX = Infinity; + let minimumY = Infinity; + let idsMap = {}; + let nodes = reactFlowInstance.getNodes(); + let edges = reactFlowInstance.getEdges(); + selectionInstance.nodes.forEach((n) => { + if (n.position.y < minimumY) { + minimumY = n.position.y; + } + if (n.position.x < minimumX) { + minimumX = n.position.x; + } + }); - const insidePosition = reactFlowInstance.project(position); - - selectionInstance.nodes.forEach((n) => { - // Generate a unique node ID - let newId = getNodeId(); - idsMap[n.id] = newId; - - // Create a new node object - const newNode: NodeType = { - id: newId, - type: "genericNode", - position: { - x: insidePosition.x + n.position.x - minimumX, - y: insidePosition.y + n.position.y - minimumY, - }, - data: { - ...n.data, - id: newId, - }, - }; - - // Add the new node to the list of nodes in state - nodes = nodes - .map((e) => ({ ...e, selected: false })) - .concat({ ...newNode, selected: false }) - }); - reactFlowInstance.setNodes(nodes); - - selectionInstance.edges.forEach((e) => { - let source = idsMap[e.source]; - let target = idsMap[e.target]; - let sourceHandleSplitted = e.sourceHandle.split("|"); - let sourceHandle = - sourceHandleSplitted[0] + - "|" + - source + - "|" + - sourceHandleSplitted.slice(2).join("|"); - let targetHandleSplitted = e.targetHandle.split("|"); - let targetHandle = - targetHandleSplitted.slice(0, -1).join("|") + "|" + target; - let id = - "reactflow__edge-" + - source + - sourceHandle + - "-" + - target + - targetHandle; - edges = addEdge( - { - source, - target, - sourceHandle, - targetHandle, - id, - className: "animate-pulse", - selected: false, - }, - edges.map((e) => ({ ...e, selected: false })) - ); - }); - reactFlowInstance.setEdges(edges); - }; - - function addFlow(flow?: FlowType) { - // Get data from the flow or set it to null if there's no flow provided. - const data = flow?.data ? flow.data : null; - const description = flow?.description ? flow.description : ""; + const insidePosition = reactFlowInstance.project(position); - if (data) { - data.nodes.forEach((node) => { - if (Object.keys(templates[node.data.type]["template"]).length > 0) { - node.data.node.template = updateTemplate( - templates[node.data.type]["template"] as unknown as APITemplateType, - node.data.node.template as APITemplateType - ); - } - }); - } - // Create a new flow with a default name if no flow is provided. - let newFlow: FlowType = { - description, - name: flow?.name ?? "New Flow", - id: uuidv4(), - data, - }; + selectionInstance.nodes.forEach((n) => { + // Generate a unique node ID + let newId = getNodeId(); + idsMap[n.id] = newId; - // Increment the ID counter. - setId(uuidv4()); + // Create a new node object + const newNode: NodeType = { + id: newId, + type: "genericNode", + position: { + x: insidePosition.x + n.position.x - minimumX, + y: insidePosition.y + n.position.y - minimumY, + }, + data: { + ...n.data, + id: newId, + }, + }; - // Add the new flow to the list of flows. - - setFlows((prevState) => { - const newFlows = [...prevState, newFlow]; - return newFlows; - }); + // Add the new node to the list of nodes in state + nodes = nodes + .map((e) => ({ ...e, selected: false })) + .concat({ ...newNode, selected: false }); + }); + reactFlowInstance.setNodes(nodes); - // Set the tab index to the new flow. - setTabIndex(flows.length); - } - /** - * Updates an existing flow with new data - * @param newFlow - The new flow object containing the updated data - */ - function updateFlow(newFlow: FlowType) { - setFlows((prevState) => { - const newFlows = [...prevState]; - const index = newFlows.findIndex((flow) => flow.id === newFlow.id); - if (index !== -1) { - newFlows[index].description = newFlow.description ?? ""; - newFlows[index].data = newFlow.data; - newFlows[index].name = newFlow.name; - } - return newFlows; - }); - } - const [disableCopyPaste, setDisableCopyPaste] = useState(false); + selectionInstance.edges.forEach((e) => { + let source = idsMap[e.source]; + let target = idsMap[e.target]; + let sourceHandleSplitted = e.sourceHandle.split("|"); + let sourceHandle = + sourceHandleSplitted[0] + + "|" + + source + + "|" + + sourceHandleSplitted.slice(2).join("|"); + let targetHandleSplitted = e.targetHandle.split("|"); + let targetHandle = + targetHandleSplitted.slice(0, -1).join("|") + "|" + target; + let id = + "reactflow__edge-" + + source + + sourceHandle + + "-" + + target + + targetHandle; + edges = addEdge( + { + source, + target, + sourceHandle, + targetHandle, + id, + className: "animate-pulse", + selected: false, + }, + edges.map((e) => ({ ...e, selected: false })) + ); + }); + reactFlowInstance.setEdges(edges); + } - return ( - - {children} - - ); -} \ No newline at end of file + function addFlow(flow?: FlowType) { + // Get data from the flow or set it to null if there's no flow provided. + const data = flow?.data ? flow.data : null; + const description = flow?.description ? flow.description : ""; + + if (data) { + data.nodes.forEach((node) => { + if (Object.keys(templates[node.data.type]["template"]).length > 0) { + node.data.node.template = updateTemplate( + templates[node.data.type]["template"] as unknown as APITemplateType, + node.data.node.template as APITemplateType + ); + } + }); + } + // Create a new flow with a default name if no flow is provided. + let newFlow: FlowType = { + description, + name: flow?.name ?? "New Flow", + id: uuidv4(), + data, + }; + + // Increment the ID counter. + setId(uuidv4()); + + // Add the new flow to the list of flows. + + setFlows((prevState) => { + const newFlows = [...prevState, newFlow]; + return newFlows; + }); + + // Set the tab index to the new flow. + setTabIndex(flows.length); + } + /** + * Updates an existing flow with new data + * @param newFlow - The new flow object containing the updated data + */ + function updateFlow(newFlow: FlowType) { + setFlows((prevState) => { + const newFlows = [...prevState]; + const index = newFlows.findIndex((flow) => flow.id === newFlow.id); + if (index !== -1) { + newFlows[index].description = newFlow.description ?? ""; + newFlows[index].data = newFlow.data; + newFlows[index].name = newFlow.name; + } + return newFlows; + }); + } + const [disableCopyPaste, setDisableCopyPaste] = useState(false); + + return ( + + {children} + + ); +} diff --git a/src/frontend/src/controllers/API/index.ts b/src/frontend/src/controllers/API/index.ts index 9a93a9b36..f6f46404b 100644 --- a/src/frontend/src/controllers/API/index.ts +++ b/src/frontend/src/controllers/API/index.ts @@ -4,40 +4,40 @@ import axios, { AxiosResponse } from "axios"; import { FlowType } from "../../types/flow"; export async function getAll(): Promise> { - return await axios.get(`/all`); + return await axios.get(`/all`); } export async function sendAll(data: sendAllProps) { - return await axios.post(`/predict`, data); + return await axios.post(`/predict`, data); } export async function checkCode( - code: string + code: string ): Promise> { - return await axios.post("/validate/code", { code }); + return await axios.post("/validate/code", { code }); } export async function checkPrompt( - template: string + template: string ): Promise> { - return await axios.post("/validate/prompt", { template }); + return await axios.post("/validate/prompt", { template }); } export async function getExamples(): Promise { - const url = - "https://api.github.com/repos/logspace-ai/langflow_examples/contents/examples"; - const response = await axios.get(url); + const url = + "https://api.github.com/repos/logspace-ai/langflow_examples/contents/examples"; + const response = await axios.get(url); - const jsonFiles = response.data.filter((file: any) => { - return file.name.endsWith(".json"); - }); + const jsonFiles = response.data.filter((file: any) => { + return file.name.endsWith(".json"); + }); - const contentsPromises = jsonFiles.map(async (file: any) => { - const contentResponse = await axios.get(file.download_url); - return contentResponse.data; - }); + const contentsPromises = jsonFiles.map(async (file: any) => { + const contentResponse = await axios.get(file.download_url); + return contentResponse.data; + }); - const contents = await Promise.all(contentsPromises); + const contents = await Promise.all(contentsPromises); - return contents; + return contents; } diff --git a/src/frontend/src/index.tsx b/src/frontend/src/index.tsx index 5857efd9a..088db15a8 100644 --- a/src/frontend/src/index.tsx +++ b/src/frontend/src/index.tsx @@ -5,16 +5,16 @@ import reportWebVitals from "./reportWebVitals"; import { BrowserRouter } from "react-router-dom"; import ContextWrapper from "./contexts"; -import './index.css'; +import "./index.css"; const root = ReactDOM.createRoot( - document.getElementById("root") as HTMLElement + document.getElementById("root") as HTMLElement ); root.render( - - - - - + + + + + ); reportWebVitals(); diff --git a/src/frontend/src/modals/ApiModal/index.tsx b/src/frontend/src/modals/ApiModal/index.tsx index f14b190f5..daeafe6bb 100644 --- a/src/frontend/src/modals/ApiModal/index.tsx +++ b/src/frontend/src/modals/ApiModal/index.tsx @@ -1,6 +1,10 @@ import { Dialog, Transition } from "@headlessui/react"; -import { IconCheck, IconClipboard, IconDownload } from '@tabler/icons-react'; -import { XMarkIcon, CommandLineIcon, CodeBracketSquareIcon } from "@heroicons/react/24/outline"; +import { IconCheck, IconClipboard, IconDownload } from "@tabler/icons-react"; +import { + XMarkIcon, + CommandLineIcon, + CodeBracketSquareIcon, +} from "@heroicons/react/24/outline"; import { Fragment, useContext, useRef, useState } from "react"; import { PopUpContext } from "../../contexts/popUpContext"; import "ace-builds/src-noconflict/mode-python"; @@ -9,42 +13,40 @@ import "ace-builds/src-noconflict/theme-twilight"; import "ace-builds/src-noconflict/ext-language_tools"; // import "ace-builds/webpack-resolver"; import { darkContext } from "../../contexts/darkContext"; -import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'; -import { oneDark } from 'react-syntax-highlighter/dist/cjs/styles/prism'; - - +import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; +import { oneDark } from "react-syntax-highlighter/dist/cjs/styles/prism"; export default function ApiModal({ flowName }) { - const [open, setOpen] = useState(true); - const { dark } = useContext(darkContext); - const { closePopUp } = useContext(PopUpContext); - const [activeTab, setActiveTab] = useState(0); - const ref = useRef(); - const [isCopied, setIsCopied] = useState(false); + const [open, setOpen] = useState(true); + const { dark } = useContext(darkContext); + const { closePopUp } = useContext(PopUpContext); + const [activeTab, setActiveTab] = useState(0); + const ref = useRef(); + const [isCopied, setIsCopied] = useState(false); - const copyToClipboard = () => { - if (!navigator.clipboard || !navigator.clipboard.writeText) { - return; - } + const copyToClipboard = () => { + if (!navigator.clipboard || !navigator.clipboard.writeText) { + return; + } - navigator.clipboard.writeText(tabs[activeTab].code).then(() => { - setIsCopied(true); + navigator.clipboard.writeText(tabs[activeTab].code).then(() => { + setIsCopied(true); - setTimeout(() => { - setIsCopied(false); - }, 2000); - }); - }; - function setModalOpen(x: boolean) { - setOpen(x); - if (x === false) { - setTimeout(() => { - closePopUp(); - }, 300); - } - } + setTimeout(() => { + setIsCopied(false); + }, 2000); + }); + }; + function setModalOpen(x: boolean) { + setOpen(x); + if (x === false) { + setTimeout(() => { + closePopUp(); + }, 300); + } + } - const pythonApiCode = `import requests + const pythonApiCode = `import requests import json API_URL = "${window.location.protocol}//${window.location.host}/predict" @@ -58,130 +60,142 @@ def predict(message): print(predict("Your message"))`; - const pythonCode = `from langflow import load_flow_from_json + const pythonCode = `from langflow import load_flow_from_json flow = load_flow_from_json("${flowName}.json") # Now you can use it like any chain flow("Hey, have you heard of LangFlow?")`; - const tabs = [ - { - name: "Python API", - mode: "python", - image: "https://images.squarespace-cdn.com/content/v1/5df3d8c5d2be5962e4f87890/1628015119369-OY4TV3XJJ53ECO0W2OLQ/Python+API+Training+Logo.png?format=1000w", - code: pythonApiCode, - }, - { - name: "Python Code", - mode: "python", - image: "https://cdn-icons-png.flaticon.com/512/5968/5968350.png", - code: pythonCode, - }, + const tabs = [ + { + name: "Python API", + mode: "python", + image: + "https://images.squarespace-cdn.com/content/v1/5df3d8c5d2be5962e4f87890/1628015119369-OY4TV3XJJ53ECO0W2OLQ/Python+API+Training+Logo.png?format=1000w", + code: pythonApiCode, + }, + { + name: "Python Code", + mode: "python", + image: "https://cdn-icons-png.flaticon.com/512/5968/5968350.png", + code: pythonCode, + }, + ]; + return ( + + + +
+ - ] - return ( - - - -
- - -
-
- - -
- -
-
-
-
-
-
- - Code - -
-
-
-
-
- {tabs.map((tab, index) => ( - - ))} -
-
-
- - Export your flow to use it with this code. - - -
- - {tabs[activeTab].code} - -
-
-
-
-
-
-
-
-
-
- ); +
+
+ + +
+ +
+
+
+
+
+
+ + Code + +
+
+
+
+
+ {tabs.map((tab, index) => ( + + ))} +
+
+
+ + Export your flow to use it with this code. + + +
+ + {tabs[activeTab].code} + +
+
+
+
+
+
+
+
+
+
+ ); } diff --git a/src/frontend/src/modals/NodeModal/components/ModalField/index.tsx b/src/frontend/src/modals/NodeModal/components/ModalField/index.tsx index 049131e6b..0c19b9611 100644 --- a/src/frontend/src/modals/NodeModal/components/ModalField/index.tsx +++ b/src/frontend/src/modals/NodeModal/components/ModalField/index.tsx @@ -13,154 +13,154 @@ import CodeAreaComponent from "../../../../components/codeAreaComponent"; import { classNames } from "../../../../utils"; export default function ModalField({ data, title, required, id, name, type }) { - const { save } = useContext(TabsContext); - const [enabled, setEnabled] = useState( - data.node.template[name]?.value ?? false - ); - const display = - type === "str" || - type === "int" || - type === "prompt" || - type === "bool" || - type === "float" || - type === "file" || - type === "code"; + const { save } = useContext(TabsContext); + const [enabled, setEnabled] = useState( + data.node.template[name]?.value ?? false + ); + const display = + type === "str" || + type === "int" || + type === "prompt" || + type === "bool" || + type === "float" || + type === "file" || + type === "code"; - return ( -
- {display && ( -
- {title} - {required ? " *" : ""} -
- )} + return ( +
+ {display && ( +
+ {title} + {required ? " *" : ""} +
+ )} - {type === "str" && !data.node.template[name].options ? ( -
- {data.node.template[name].list ? ( - { - data.node.template[name].value = t; - save(); - }} - /> - ) : data.node.template[name].multiline ? ( - { - data.node.template[name].value = t; - save(); - }} - /> - ) : ( - { - data.node.template[name].value = t; - save(); - }} - /> - )} -
- ) : type === "bool" ? ( -
- {" "} - { - data.node.template[name].value = t; - setEnabled(t); - save(); - }} - /> -
- ) : type === "float" ? ( -
- { - data.node.template[name].value = t; - save(); - }} - /> -
- ) : type === "str" && data.node.template[name].options ? ( -
- (data.node.template[name].value = newValue)} - value={data.node.template[name].value ?? "Choose an option"} - > -
- ) : type === "int" ? ( -
- { - data.node.template[name].value = t; - save(); - }} - /> -
- ) : type === "file" ? ( -
- { - data.node.template[name].value = t; - }} - fileTypes={data.node.template[name].fileTypes} - suffixes={data.node.template[name].suffixes} - onFileChange={(t: string) => { - data.node.template[name].content = t; - save(); - }} - > -
- ) : type === "prompt" ? ( -
- { - data.node.template[name].value = t; - save(); - }} - /> -
- ) : type === "code" ? ( -
- { - data.node.template[name].value = t; - save(); - }} - /> -
- ) : ( -
- )} -
- ); + {type === "str" && !data.node.template[name].options ? ( +
+ {data.node.template[name].list ? ( + { + data.node.template[name].value = t; + save(); + }} + /> + ) : data.node.template[name].multiline ? ( + { + data.node.template[name].value = t; + save(); + }} + /> + ) : ( + { + data.node.template[name].value = t; + save(); + }} + /> + )} +
+ ) : type === "bool" ? ( +
+ {" "} + { + data.node.template[name].value = t; + setEnabled(t); + save(); + }} + /> +
+ ) : type === "float" ? ( +
+ { + data.node.template[name].value = t; + save(); + }} + /> +
+ ) : type === "str" && data.node.template[name].options ? ( +
+ (data.node.template[name].value = newValue)} + value={data.node.template[name].value ?? "Choose an option"} + > +
+ ) : type === "int" ? ( +
+ { + data.node.template[name].value = t; + save(); + }} + /> +
+ ) : type === "file" ? ( +
+ { + data.node.template[name].value = t; + }} + fileTypes={data.node.template[name].fileTypes} + suffixes={data.node.template[name].suffixes} + onFileChange={(t: string) => { + data.node.template[name].content = t; + save(); + }} + > +
+ ) : type === "prompt" ? ( +
+ { + data.node.template[name].value = t; + save(); + }} + /> +
+ ) : type === "code" ? ( +
+ { + data.node.template[name].value = t; + save(); + }} + /> +
+ ) : ( +
+ )} +
+ ); } diff --git a/src/frontend/src/modals/NodeModal/index.tsx b/src/frontend/src/modals/NodeModal/index.tsx index 1bc73af6f..257ccffa4 100644 --- a/src/frontend/src/modals/NodeModal/index.tsx +++ b/src/frontend/src/modals/NodeModal/index.tsx @@ -8,138 +8,138 @@ import { typesContext } from "../../contexts/typesContext"; import ModalField from "./components/ModalField"; export default function NodeModal({ 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 Icon = nodeIcons[types[data.type]]; - return ( - - - -
- + 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 Icon = nodeIcons[types[data.type]]; + return ( + + + +
+ -
-
- - -
- -
-
-
- -
- - {data.type} - -
-
-
-
-
-
- {Object.keys(data.node.template) - .filter( - (t) => - t.charAt(0) !== "_" && - data.node.template[t].advanced && - data.node.template[t].show - ) - .map((t: string, idx) => { - return ( - - ); - })} -
-
-
-
-
- -
-
-
-
-
-
-
-
- ); +
+
+ + +
+ +
+
+
+ +
+ + {data.type} + +
+
+
+
+
+
+ {Object.keys(data.node.template) + .filter( + (t) => + t.charAt(0) !== "_" && + data.node.template[t].advanced && + data.node.template[t].show + ) + .map((t: string, idx) => { + return ( + + ); + })} +
+
+
+
+
+ +
+
+
+
+
+
+
+
+ ); } diff --git a/src/frontend/src/modals/chatModal/chatMessage/codeBlock/index.tsx b/src/frontend/src/modals/chatModal/chatMessage/codeBlock/index.tsx index ed67a9af5..851f5118a 100644 --- a/src/frontend/src/modals/chatModal/chatMessage/codeBlock/index.tsx +++ b/src/frontend/src/modals/chatModal/chatMessage/codeBlock/index.tsx @@ -5,78 +5,78 @@ import { oneDark } from "react-syntax-highlighter/dist/cjs/styles/prism"; import { programmingLanguages } from "../../../../utils"; interface Props { - language: string; - value: string; + language: string; + value: string; } export const CodeBlock: FC = memo(({ language, value }) => { - const [isCopied, setIsCopied] = useState(false); + const [isCopied, setIsCopied] = useState(false); - const copyToClipboard = () => { - if (!navigator.clipboard || !navigator.clipboard.writeText) { - return; - } + const copyToClipboard = () => { + if (!navigator.clipboard || !navigator.clipboard.writeText) { + return; + } - navigator.clipboard.writeText(value).then(() => { - setIsCopied(true); + navigator.clipboard.writeText(value).then(() => { + setIsCopied(true); - setTimeout(() => { - setIsCopied(false); - }, 2000); - }); - }; - const downloadAsFile = () => { - const fileExtension = programmingLanguages[language] || ".file"; - const suggestedFileName = `${"generated-code"}${fileExtension}`; - const fileName = window.prompt("enter file name", suggestedFileName); + setTimeout(() => { + setIsCopied(false); + }, 2000); + }); + }; + const downloadAsFile = () => { + const fileExtension = programmingLanguages[language] || ".file"; + const suggestedFileName = `${"generated-code"}${fileExtension}`; + const fileName = window.prompt("enter file name", suggestedFileName); - if (!fileName) { - // user pressed cancel on prompt - return; - } + if (!fileName) { + // user pressed cancel on prompt + return; + } - const blob = new Blob([value], { type: "text/plain" }); - const url = URL.createObjectURL(blob); - const link = document.createElement("a"); - link.download = fileName; - link.href = url; - link.style.display = "none"; - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); - URL.revokeObjectURL(url); - }; - return ( -
-
- {language} + const blob = new Blob([value], { type: "text/plain" }); + const url = URL.createObjectURL(blob); + const link = document.createElement("a"); + link.download = fileName; + link.href = url; + link.style.display = "none"; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + URL.revokeObjectURL(url); + }; + return ( +
+
+ {language} -
- - -
-
+
+ + +
+
- - {value} - -
- ); + + {value} + +
+ ); }); CodeBlock.displayName = "CodeBlock"; diff --git a/src/frontend/src/modals/chatModal/chatMessage/index.tsx b/src/frontend/src/modals/chatModal/chatMessage/index.tsx index f7131e1e5..5e0f3e051 100644 --- a/src/frontend/src/modals/chatModal/chatMessage/index.tsx +++ b/src/frontend/src/modals/chatModal/chatMessage/index.tsx @@ -3,7 +3,7 @@ import { useEffect, useRef, useState } from "react"; import { ChatMessageType } from "../../../types/chat"; import { classNames } from "../../../utils"; import AiIcon from "../../../assets/Gooey Ring-5s-271px.svg"; -import AiIconStill from "../../../assets/froze-flow.png" +import AiIconStill from "../../../assets/froze-flow.png"; import { UserIcon } from "@heroicons/react/24/solid"; import FileCard from "../fileComponent"; import ReactMarkdown from "react-markdown"; @@ -13,132 +13,154 @@ import remarkMath from "remark-math"; import { CodeBlock } from "./codeBlock"; import Convert from "ansi-to-html"; -export default function ChatMessage({ chat, lockChat }: { chat: ChatMessageType, lockChat: boolean }) { - const convert = new Convert({ newline: true }); - const [message, setMessage] = useState(""); - const imgRef = useRef(null); - useEffect(() => { - setMessage(chat.message); - }, [chat.message]); - const [hidden, setHidden] = useState(true); - return ( -
-
- {!chat.isSend &&
- - -
} - {chat.isSend && } -
- {!chat.isSend ? ( -
-
- {hidden && chat.thought && chat.thought !== "" && ( -
setHidden((prev) => !prev)} - className="absolute -top-1 -left-2 cursor-pointer" - > - -
- )} - {chat.thought && chat.thought !== "" && !hidden && ( -
setHidden((prev) => !prev)} - className=" text-start inline-block rounded-md text-gray-600 dark:text-gray-200 h-full border border-gray-300 dark:border-gray-500 +export default function ChatMessage({ + chat, + lockChat, +}: { + chat: ChatMessageType; + lockChat: boolean; +}) { + const convert = new Convert({ newline: true }); + const [message, setMessage] = useState(""); + const imgRef = useRef(null); + useEffect(() => { + setMessage(chat.message); + }, [chat.message]); + const [hidden, setHidden] = useState(true); + return ( +
+
+ {!chat.isSend && ( +
+ + +
+ )} + {chat.isSend && ( + + )} +
+ {!chat.isSend ? ( +
+
+ {hidden && chat.thought && chat.thought !== "" && ( +
setHidden((prev) => !prev)} + className="absolute -top-1 -left-2 cursor-pointer" + > + +
+ )} + {chat.thought && chat.thought !== "" && !hidden && ( +
setHidden((prev) => !prev)} + className=" text-start inline-block rounded-md text-gray-600 dark:text-gray-200 h-full border border-gray-300 dark:border-gray-500 bg-gray-100 dark:bg-gray-800 w-[95%] pb-3 pt-3 px-2 ml-3 cursor-pointer scrollbar-hide overflow-scroll" - dangerouslySetInnerHTML={{ - __html: convert.toHtml(chat.thought), - }} - >
- )} - {chat.thought && chat.thought !== "" && !hidden &&

} -
-
-
- - ▍ - - ); - } + dangerouslySetInnerHTML={{ + __html: convert.toHtml(chat.thought), + }} + >
+ )} + {chat.thought && chat.thought !== "" && !hidden &&

} +
+
+
+ + ▍ + + ); + } - children[0] = (children[0] as string).replace( - "`▍`", - "▍" - ); - } + children[0] = (children[0] as string).replace( + "`▍`", + "▍" + ); + } - const match = /language-(\w+)/.exec(className || ""); + const match = /language-(\w+)/.exec(className || ""); - return !inline ? ( - - ) : ( - - {children} - - ); - }, - }} - > - {message} - -
- {chat.files && ( -
- {chat.files.map((file, index) => { - return ( -
- -
- ); - })} -
- )} -
-
-
-
- ) : ( -
-
- - {message} - -
-
- )} -
- ); + return !inline ? ( + + ) : ( + + {children} + + ); + }, + }} + > + {message} + +
+ {chat.files && ( +
+ {chat.files.map((file, index) => { + return ( +
+ +
+ ); + })} +
+ )} +
+
+
+
+ ) : ( +
+
+ + {message} + +
+
+ )} +
+ ); } diff --git a/src/frontend/src/modals/chatModal/fileComponent/index.tsx b/src/frontend/src/modals/chatModal/fileComponent/index.tsx index 1ffb1da01..3d4feb1d5 100644 --- a/src/frontend/src/modals/chatModal/fileComponent/index.tsx +++ b/src/frontend/src/modals/chatModal/fileComponent/index.tsx @@ -3,77 +3,77 @@ import * as base64js from "base64-js"; import { useState } from "react"; export default function FileCard({ fileName, content, fileType }) { - const handleDownload = () => { - const byteArray = new Uint8Array(base64js.toByteArray(content)); - const blob = new Blob([byteArray], { type: "application/octet-stream" }); - const url = URL.createObjectURL(blob); - const link = document.createElement("a"); - link.href = url; - link.download = fileName + ".png"; - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); - URL.revokeObjectURL(url); - }; - const [isHovered, setIsHovered] = useState(false); - function handleMouseEnter() { - setIsHovered(true); - } - function handleMouseLeave() { - setIsHovered(false); - } + const handleDownload = () => { + const byteArray = new Uint8Array(base64js.toByteArray(content)); + const blob = new Blob([byteArray], { type: "application/octet-stream" }); + const url = URL.createObjectURL(blob); + const link = document.createElement("a"); + link.href = url; + link.download = fileName + ".png"; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + URL.revokeObjectURL(url); + }; + const [isHovered, setIsHovered] = useState(false); + function handleMouseEnter() { + setIsHovered(true); + } + function handleMouseLeave() { + setIsHovered(false); + } - if (fileType === "image") { - return ( -
- generated image - {isHovered && ( -
- -
- )} -
- ); - } + if (fileType === "image") { + return ( +
+ generated image + {isHovered && ( +
+ +
+ )} +
+ ); + } - return ( - - ); + return ( + + ); } diff --git a/src/frontend/src/modals/chatModal/index.tsx b/src/frontend/src/modals/chatModal/index.tsx index 20080ad7f..399febebe 100644 --- a/src/frontend/src/modals/chatModal/index.tsx +++ b/src/frontend/src/modals/chatModal/index.tsx @@ -236,11 +236,14 @@ export default function ChatModal({ }, []); useEffect(() => { - if((ws.current.readyState=== ws.current.CLOSED || ws.current.readyState=== ws.current.CLOSING)){ + if ( + ws.current.readyState === ws.current.CLOSED || + ws.current.readyState === ws.current.CLOSING + ) { connectWS(); setLockChat(false); } - },[lockChat]); + }, [lockChat]); async function sendAll(data: sendAllProps) { try { @@ -346,7 +349,7 @@ export default function ChatModal({ function clearChat() { setChatHistory([]); ws.current.send(JSON.stringify({ clear_history: true })); - if(lockChat) setLockChat(false); + if (lockChat) setLockChat(false); } function setModalOpen(x: boolean) { diff --git a/src/frontend/src/modals/codeAreaModal/index.tsx b/src/frontend/src/modals/codeAreaModal/index.tsx index 77ebf45c1..2a14fabe6 100644 --- a/src/frontend/src/modals/codeAreaModal/index.tsx +++ b/src/frontend/src/modals/codeAreaModal/index.tsx @@ -13,164 +13,164 @@ import { checkCode } from "../../controllers/API"; import { alertContext } from "../../contexts/alertContext"; import { TabsContext } from "../../contexts/tabsContext"; export default function CodeAreaModal({ - value, - setValue, + value, + setValue, }: { - setValue: (value: string) => void; - value: string; + setValue: (value: string) => void; + value: string; }) { - const [open, setOpen] = useState(true); - const [code, setCode] = useState(value); - const { dark } = useContext(darkContext); - const { setErrorData, setSuccessData } = useContext(alertContext); - const { closePopUp } = useContext(PopUpContext); - const ref = useRef(); - function setModalOpen(x: boolean) { - setOpen(x); - if (x === false) { - setTimeout(() => { - closePopUp(); - }, 300); - } - } - return ( - - - -
- + const [open, setOpen] = useState(true); + const [code, setCode] = useState(value); + const { dark } = useContext(darkContext); + const { setErrorData, setSuccessData } = useContext(alertContext); + const { closePopUp } = useContext(PopUpContext); + const ref = useRef(); + function setModalOpen(x: boolean) { + setOpen(x); + if (x === false) { + setTimeout(() => { + closePopUp(); + }, 300); + } + } + return ( + + + +
+ -
-
- - -
- -
-
-
-
-
-
- - Edit Code - -
-
-
-
-
- { - setCode(value); - }} - className="h-full w-full rounded-lg" - /> -
-
-
-
- -
-
-
-
-
-
-
-
- ); +
+
+ + +
+ +
+
+
+
+
+
+ + Edit Code + +
+
+
+
+
+ { + setCode(value); + }} + className="h-full w-full rounded-lg" + /> +
+
+
+
+ +
+
+
+
+
+
+
+
+ ); } diff --git a/src/frontend/src/modals/exportModal/index.tsx b/src/frontend/src/modals/exportModal/index.tsx index 44b8d7992..6bcedc60c 100644 --- a/src/frontend/src/modals/exportModal/index.tsx +++ b/src/frontend/src/modals/exportModal/index.tsx @@ -1,9 +1,9 @@ import { Dialog, Transition } from "@headlessui/react"; import { - XMarkIcon, - ArrowDownTrayIcon, - DocumentDuplicateIcon, - ComputerDesktopIcon, + XMarkIcon, + ArrowDownTrayIcon, + DocumentDuplicateIcon, + ComputerDesktopIcon, } from "@heroicons/react/24/outline"; import { Fragment, useContext, useRef, useState } from "react"; import { alertContext } from "../../contexts/alertContext"; @@ -12,170 +12,169 @@ import { TabsContext } from "../../contexts/tabsContext"; import { removeApiKeys } from "../../utils"; export default function ExportModal() { - const [open, setOpen] = useState(true); - const { closePopUp } = useContext(PopUpContext); - const ref = useRef(); - const { setErrorData } = useContext(alertContext); - const { flows, tabIndex, updateFlow, downloadFlow } = useContext(TabsContext); - function setModalOpen(x: boolean) { - setOpen(x); - if (x === false) { - setTimeout(() => { - closePopUp(); - }, 300); - } - } - const [checked, setChecked] = useState(true); - const [name, setName] = useState(flows[tabIndex].name); - return ( - - - -
- + const [open, setOpen] = useState(true); + const { closePopUp } = useContext(PopUpContext); + const ref = useRef(); + const { setErrorData } = useContext(alertContext); + const { flows, tabIndex, updateFlow, downloadFlow } = useContext(TabsContext); + function setModalOpen(x: boolean) { + setOpen(x); + if (x === false) { + setTimeout(() => { + closePopUp(); + }, 300); + } + } + const [checked, setChecked] = useState(true); + const [name, setName] = useState(flows[tabIndex].name); + return ( + + + +
+ -
-
- - -
- -
-
-
-
-
-
- - Export as - -
-
-
-
- - { - if (event.target.value != "") { - let newFlow = flows[tabIndex]; - newFlow.name = event.target.value; - setName(event.target.value); - updateFlow(newFlow); - } else { - setName(event.target.value); - } - }} - type="text" - name="name" - value={name ?? null} - placeholder="File name" - id="name" - className="focus:border focus:border-blue block w-full px-3 py-2 border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-800 dark:border-gray-600 dark:focus:border-blue-500 dark:focus:ring-blue-500 text-gray-900 dark:text-gray-100" - /> -
-
- - -
+
+
+ + +
+ +
+
+
+
+
+
+ + Export as + +
+
+
+
+ + { + if (event.target.value != "") { + let newFlow = flows[tabIndex]; + newFlow.name = event.target.value; + setName(event.target.value); + updateFlow(newFlow); + } else { + setName(event.target.value); + } + }} + type="text" + name="name" + value={name ?? null} + placeholder="File name" + id="name" + className="focus:border focus:border-blue block w-full px-3 py-2 border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-800 dark:border-gray-600 dark:focus:border-blue-500 dark:focus:ring-blue-500 text-gray-900 dark:text-gray-100" + /> +
+
+ + +
-
- -
-
- -
-
-
-
-
-
-
-
-
- ); +
+ +
+
+ +
+
+ + +
+ + +
+
+ ); } diff --git a/src/frontend/src/modals/importModal/buttonBox/index.tsx b/src/frontend/src/modals/importModal/buttonBox/index.tsx index b8e51e388..2c408a120 100644 --- a/src/frontend/src/modals/importModal/buttonBox/index.tsx +++ b/src/frontend/src/modals/importModal/buttonBox/index.tsx @@ -33,48 +33,47 @@ export default function ButtonBox({ let textHeight: number; let textWidth: number; switch (size) { - case "small": - bigCircle = "h-12 w-12"; - smallCircle = "h-8 w-8"; - titleFontSize = "text-sm"; - descriptionFontSize = "text-xs"; - padding = "p-2 py-3"; - marginTop = "mt-2"; - height = "h-36"; - width = "w-32"; - break; - case "medium": - bigCircle = "h-16 w-16"; - smallCircle = "h-12 w-12"; - titleFontSize = "text-base"; - descriptionFontSize = "text-sm"; - padding = "p-4 py-5"; - marginTop = "mt-3"; - height = "h-44"; - width = "w-36"; - break; - case "big": - bigCircle = "h-20 w-20"; - smallCircle = "h-16 w-16"; - titleFontSize = "text-lg"; - descriptionFontSize = "text-sm"; - padding = "p-8 py-10"; - marginTop = "mt-6"; - height = "h-56"; - width = "w-44"; - break; - default: - bigCircle = "h-20 w-20"; - smallCircle = "h-16 w-16"; - titleFontSize = "text-lg"; - descriptionFontSize = "text-sm"; - padding = "p-8 py-10"; - marginTop = "mt-6"; - height = "h-56"; - width = "w-44"; - break; - } - + case "small": + bigCircle = "h-12 w-12"; + smallCircle = "h-8 w-8"; + titleFontSize = "text-sm"; + descriptionFontSize = "text-xs"; + padding = "p-2 py-3"; + marginTop = "mt-2"; + height = "h-36"; + width = "w-32"; + break; + case "medium": + bigCircle = "h-16 w-16"; + smallCircle = "h-12 w-12"; + titleFontSize = "text-base"; + descriptionFontSize = "text-sm"; + padding = "p-4 py-5"; + marginTop = "mt-3"; + height = "h-44"; + width = "w-36"; + break; + case "big": + bigCircle = "h-20 w-20"; + smallCircle = "h-16 w-16"; + titleFontSize = "text-lg"; + descriptionFontSize = "text-sm"; + padding = "p-8 py-10"; + marginTop = "mt-6"; + height = "h-56"; + width = "w-44"; + break; + default: + bigCircle = "h-20 w-20"; + smallCircle = "h-16 w-16"; + titleFontSize = "text-lg"; + descriptionFontSize = "text-sm"; + padding = "p-8 py-10"; + marginTop = "mt-6"; + height = "h-56"; + width = "w-44"; + break; + } return ( ); diff --git a/src/frontend/src/modals/importModal/index.tsx b/src/frontend/src/modals/importModal/index.tsx index 2d3ef979a..aa25e058b 100644 --- a/src/frontend/src/modals/importModal/index.tsx +++ b/src/frontend/src/modals/importModal/index.tsx @@ -1,11 +1,11 @@ import { Dialog, Transition } from "@headlessui/react"; import { - XMarkIcon, - ArrowDownTrayIcon, - DocumentDuplicateIcon, - ComputerDesktopIcon, - ArrowUpTrayIcon, - ArrowLeftIcon, + XMarkIcon, + ArrowDownTrayIcon, + DocumentDuplicateIcon, + ComputerDesktopIcon, + ArrowUpTrayIcon, + ArrowLeftIcon, } from "@heroicons/react/24/outline"; import { Fragment, useContext, useRef, useState } from "react"; import { PopUpContext } from "../../contexts/popUpContext"; @@ -19,214 +19,214 @@ import { FlowType } from "../../types/flow"; import { classNames, snakeToSpaces, toNormalCase } from "../../utils"; export default function ImportModal() { - const [open, setOpen] = useState(true); - const { setErrorData } = useContext(alertContext); - const { closePopUp } = useContext(PopUpContext); - const ref = useRef(); - const [showExamples, setShowExamples] = useState(false); - const [loadingExamples, setLoadingExamples] = useState(false); - const [examples, setExamples] = useState([]); - const { uploadFlow, addFlow } = useContext(TabsContext); - function setModalOpen(x: boolean) { - setOpen(x); - if (x === false) { - setTimeout(() => { - closePopUp(); - }, 300); - } - } + const [open, setOpen] = useState(true); + const { setErrorData } = useContext(alertContext); + const { closePopUp } = useContext(PopUpContext); + const ref = useRef(); + const [showExamples, setShowExamples] = useState(false); + const [loadingExamples, setLoadingExamples] = useState(false); + const [examples, setExamples] = useState([]); + const { uploadFlow, addFlow } = useContext(TabsContext); + function setModalOpen(x: boolean) { + setOpen(x); + if (x === false) { + setTimeout(() => { + closePopUp(); + }, 300); + } + } - function handleExamples() { - setLoadingExamples(true); - getExamples() - .then((result) => { - setLoadingExamples(false); - setExamples(result); - }) - .catch((error) => - setErrorData({ - title: "there was an error loading examples, please try again", - list: [error.message], - }) - ); - } + function handleExamples() { + setLoadingExamples(true); + getExamples() + .then((result) => { + setLoadingExamples(false); + setExamples(result); + }) + .catch((error) => + setErrorData({ + title: "there was an error loading examples, please try again", + list: [error.message], + }) + ); + } - return ( - - - -
- + return ( + + + +
+ -
-
- - -
- -
- {showExamples && ( - <> -
- -
- - )} -
-
-
-
-
- - {showExamples ? "Select an example" : "Import from"} - -
-
-
- {!showExamples && ( -
- - } - onClick={() => { - setShowExamples(true); - handleExamples(); - }} - textColor="text-emerald-500 dark:text-emerald-500/75" - title="Examples" - > - - } - onClick={() => { - uploadFlow(); - setModalOpen(false); - }} - textColor="text-blue-500 dark:text-blue-500/75" - title="Local File" - > -
- )} - {showExamples && loadingExamples && ( -
- -
- )} - {showExamples && - !loadingExamples && - examples.map((example, index) => { - return ( -
- {" "} - - } - onClick={() => { - addFlow(example); - setModalOpen(false); - }} - textColor="text-emerald-500 dark:text-emerald-500/75" - title={example.name} - > -
- ); - })} -
- -
-
-
-
-
-
-
- ); +
+
+ + +
+ +
+ {showExamples && ( + <> +
+ +
+ + )} +
+
+
+
+
+ + {showExamples ? "Select an example" : "Import from"} + +
+
+
+ {!showExamples && ( +
+ + } + onClick={() => { + setShowExamples(true); + handleExamples(); + }} + textColor="text-emerald-500 dark:text-emerald-500/75" + title="Examples" + > + + } + onClick={() => { + uploadFlow(); + setModalOpen(false); + }} + textColor="text-blue-500 dark:text-blue-500/75" + title="Local File" + > +
+ )} + {showExamples && loadingExamples && ( +
+ +
+ )} + {showExamples && + !loadingExamples && + examples.map((example, index) => { + return ( +
+ {" "} + + } + onClick={() => { + addFlow(example); + setModalOpen(false); + }} + textColor="text-emerald-500 dark:text-emerald-500/75" + title={example.name} + > +
+ ); + })} +
+ +
+
+
+
+
+
+
+ ); } diff --git a/src/frontend/src/modals/promptModal/index.tsx b/src/frontend/src/modals/promptModal/index.tsx index 5dbeb2264..508042a1c 100644 --- a/src/frontend/src/modals/promptModal/index.tsx +++ b/src/frontend/src/modals/promptModal/index.tsx @@ -6,148 +6,148 @@ import { darkContext } from "../../contexts/darkContext"; import { checkPrompt } from "../../controllers/API"; import { alertContext } from "../../contexts/alertContext"; export default function PromptAreaModal({ - value, - setValue, + value, + setValue, }: { - setValue: (value: string) => void; - value: string; + setValue: (value: string) => void; + value: string; }) { - const [open, setOpen] = useState(true); - const [myValue, setMyValue] = useState(value); - const { dark } = useContext(darkContext); - const { setErrorData, setSuccessData } = useContext(alertContext); - const { closePopUp } = useContext(PopUpContext); - const ref = useRef(); - function setModalOpen(x: boolean) { - setOpen(x); - if (x === false) { - setTimeout(() => { - closePopUp(); - }, 300); - } - } - return ( - - - -
- + const [open, setOpen] = useState(true); + const [myValue, setMyValue] = useState(value); + const { dark } = useContext(darkContext); + const { setErrorData, setSuccessData } = useContext(alertContext); + const { closePopUp } = useContext(PopUpContext); + const ref = useRef(); + function setModalOpen(x: boolean) { + setOpen(x); + if (x === false) { + setTimeout(() => { + closePopUp(); + }, 300); + } + } + return ( + + + +
+ -
-
- - -
- -
-
-
-
-
-
- - Edit Prompt - -
-
-
-
-
-