From 712d019f1e2c5685afd64f81b02ee331aa2690cb Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Thu, 6 Jun 2024 14:20:59 -0300 Subject: [PATCH 01/31] Added play on hover of entire node --- .../src/customNodes/genericNode/index.tsx | 70 +++++++++++-------- 1 file changed, 39 insertions(+), 31 deletions(-) diff --git a/src/frontend/src/customNodes/genericNode/index.tsx b/src/frontend/src/customNodes/genericNode/index.tsx index 5f145d523..c007caab3 100644 --- a/src/frontend/src/customNodes/genericNode/index.tsx +++ b/src/frontend/src/customNodes/genericNode/index.tsx @@ -56,14 +56,14 @@ export default function GenericNode({ const [nodeName, setNodeName] = useState(data.node!.display_name); const [inputDescription, setInputDescription] = useState(false); const [nodeDescription, setNodeDescription] = useState( - data.node?.description! + data.node?.description!, ); const [isOutdated, setIsOutdated] = useState(false); const buildStatus = useFlowStore( - (state) => state.flowBuildStatus[data.id]?.status + (state) => state.flowBuildStatus[data.id]?.status, ); const lastRunTime = useFlowStore( - (state) => state.flowBuildStatus[data.id]?.timestamp + (state) => state.flowBuildStatus[data.id]?.timestamp, ); const [validationStatus, setValidationStatus] = useState(null); @@ -116,7 +116,7 @@ export default function GenericNode({ updateNodeInternals(data.id); }, - [data.id, data.node, setNode, setIsOutdated] + [data.id, data.node, setNode, setIsOutdated], ); if (!data.node!.template) { @@ -255,8 +255,17 @@ export default function GenericNode({ const isDark = useDarkStore((state) => state.dark); const renderIconStatus = ( buildStatus: BuildStatus | undefined, - validationStatus: validationStatusType | null + validationStatus: validationStatusType | null, ) => { + const conditionSuccess = validationStatus && validationStatus.valid; + const conditionInactive = + validationStatus && + !validationStatus.valid && + buildStatus === BuildStatus.INACTIVE; + const conditionError = + buildStatus === BuildStatus.ERROR || + (validationStatus && !validationStatus.valid); + if (buildStatus === BuildStatus.BUILDING) { return ; } else { @@ -264,31 +273,30 @@ export default function GenericNode({ <> - {validationStatus && validationStatus.valid ? ( + {conditionSuccess ? ( - ) : validationStatus && - !validationStatus.valid && - buildStatus === BuildStatus.INACTIVE ? ( + ) : conditionInactive ? ( - ) : buildStatus === BuildStatus.ERROR || - (validationStatus && !validationStatus.valid) ? ( + ) : conditionError ? ( ) : ( - + <> )} ); @@ -296,7 +304,7 @@ export default function GenericNode({ }; const getSpecificClassFromBuildStatus = ( buildStatus: BuildStatus | undefined, - validationStatus: validationStatusType | null + validationStatus: validationStatusType | null, ) => { let isInvalid = validationStatus && !validationStatus.valid; @@ -320,11 +328,11 @@ export default function GenericNode({ selected: boolean, showNode: boolean, buildStatus: BuildStatus | undefined, - validationStatus: validationStatusType | null + validationStatus: validationStatusType | null, ) => { const specificClassFromBuildStatus = getSpecificClassFromBuildStatus( buildStatus, - validationStatus + validationStatus, ); const baseBorderClass = getBaseBorderClass(selected); @@ -332,8 +340,8 @@ export default function GenericNode({ const names = classNames( baseBorderClass, nodeSizeClass, - "generic-node-div", - specificClassFromBuildStatus + "generic-node-div group/node", + specificClassFromBuildStatus, ); return names; }; @@ -393,7 +401,7 @@ export default function GenericNode({ selected, showNode, buildStatus, - validationStatus + validationStatus, )} > {data.node?.beta && showNode && ( @@ -524,7 +532,7 @@ export default function GenericNode({ } title={getFieldTitle( data.node?.template!, - templateField + templateField, )} info={data.node?.template[templateField].info} name={templateField} @@ -552,7 +560,7 @@ export default function GenericNode({ proxy={data.node?.template[templateField].proxy} showNode={showNode} /> - ) + ), )} { setInputDescription(true); @@ -771,13 +779,13 @@ export default function GenericNode({ } title={getFieldTitle( data.node?.template!, - templateField + templateField, )} info={data.node?.template[templateField].info} name={templateField} tooltipTitle={ data.node?.template[templateField].input_types?.join( - "\n" + "\n", ) ?? data.node?.template[templateField].type } required={data.node!.template[templateField].required} @@ -804,7 +812,7 @@ export default function GenericNode({
{" "} From 7c28bb2bd693668d1797bf430af8247019d42765 Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Thu, 6 Jun 2024 14:35:12 -0300 Subject: [PATCH 02/31] Added Export handler on Main Page --- .../components/componentsComponent/index.tsx | 45 ++++++++++++++----- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/src/frontend/src/pages/MainPage/components/componentsComponent/index.tsx b/src/frontend/src/pages/MainPage/components/componentsComponent/index.tsx index f7d52c611..3e167db13 100644 --- a/src/frontend/src/pages/MainPage/components/componentsComponent/index.tsx +++ b/src/frontend/src/pages/MainPage/components/componentsComponent/index.tsx @@ -18,6 +18,8 @@ import { getNameByType } from "../../utils/get-name-by-type"; import { sortFlows } from "../../utils/sort-flows"; import EmptyComponent from "../emptyComponent"; import HeaderComponent from "../headerComponent"; +import { downloadFlow, removeApiKeys } from "../../../../utils/reactflowUtils"; +import { useDarkStore } from "../../../../stores/darkStore"; export default function ComponentsComponent({ type = "all", @@ -31,22 +33,22 @@ export default function ComponentsComponent({ const allFlows = useFlowsManagerStore((state) => state.allFlows); const flowsFromFolder = useFolderStore( - (state) => state.selectedFolder?.flows + (state) => state.selectedFolder?.flows, ); const setSuccessData = useAlertStore((state) => state.setSuccessData); const setErrorData = useAlertStore((state) => state.setErrorData); const [openDelete, setOpenDelete] = useState(false); const searchFlowsComponents = useFlowsManagerStore( - (state) => state.searchFlowsComponents + (state) => state.searchFlowsComponents, ); const setSelectedFlowsComponentsCards = useFlowsManagerStore( - (state) => state.setSelectedFlowsComponentsCards + (state) => state.setSelectedFlowsComponentsCards, ); const selectedFlowsComponentsCards = useFlowsManagerStore( - (state) => state.selectedFlowsComponentsCards + (state) => state.selectedFlowsComponentsCards, ); const [handleFileDrop] = useFileDrop(uploadFlow, type)!; @@ -82,7 +84,7 @@ export default function ComponentsComponent({ f.name.toLowerCase().includes(searchFlowsComponents.toLowerCase()) || f.description .toLowerCase() - .includes(searchFlowsComponents.toLowerCase()) + .includes(searchFlowsComponents.toLowerCase()), ); if (searchFlowsComponents === "") { @@ -129,6 +131,8 @@ export default function ComponentsComponent({ setOpenDelete(true); } else if (action === "duplicate") { handleDuplicate(); + } else if (action === "exprot") { + handleExport(); } }; @@ -137,9 +141,9 @@ export default function ComponentsComponent({ selectedFlowsComponentsCards.map((selectedFlow) => addFlow( true, - allFlows.find((flow) => flow.id === selectedFlow) - ) - ) + allFlows.find((flow) => flow.id === selectedFlow), + ), + ), ).then(() => { resetFilter(); getFoldersApi(true); @@ -152,6 +156,26 @@ export default function ComponentsComponent({ }); }; + const version = useDarkStore((state) => state.version); + + const handleExport = () => { + selectedFlowsComponentsCards.map((selectedFlowId) => { + const selectedFlow = allFlows.find((flow) => flow.id === selectedFlowId); + downloadFlow( + removeApiKeys({ + id: selectedFlow!.id, + data: selectedFlow!.data!, + description: selectedFlow!.description, + name: selectedFlow!.name, + last_tested_version: version, + is_component: false, + }), + selectedFlow!.name, + selectedFlow!.description, + ); + }); + }; + const handleDeleteMultiple = () => { removeFlow(selectedFlowsComponentsCards) .then(() => { @@ -180,7 +204,7 @@ export default function ComponentsComponent({ return true; } return false; - } + }, ); setSelectedFlowsComponentsCards(selectedFlows); @@ -215,7 +239,7 @@ export default function ComponentsComponent({ if (type === "all") return allFlows?.length; return allFlows?.filter( - (f) => (f.is_component ?? false) === (type === "component") + (f) => (f.is_component ?? false) === (type === "component"), )?.length; }; @@ -226,6 +250,7 @@ export default function ComponentsComponent({ handleDelete={() => handleSelectOptionsChange("delete")} handleSelectAll={handleSelectAll} handleDuplicate={() => handleSelectOptionsChange("duplicate")} + handleExport={() => handleSelectOptionsChange("export")} disableFunctions={!(selectedFlowsComponentsCards?.length > 0)} /> )} From 5b1de707fa72cd6a00f52ce1202769b523ca11f0 Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Thu, 6 Jun 2024 14:37:30 -0300 Subject: [PATCH 03/31] Added handleExport as parameter of header and added button to export --- .../components/headerComponent/index.tsx | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/frontend/src/pages/MainPage/components/headerComponent/index.tsx b/src/frontend/src/pages/MainPage/components/headerComponent/index.tsx index 2d2e43a2a..756fda03c 100644 --- a/src/frontend/src/pages/MainPage/components/headerComponent/index.tsx +++ b/src/frontend/src/pages/MainPage/components/headerComponent/index.tsx @@ -8,6 +8,7 @@ type HeaderComponentProps = { handleSelectAll: (select) => void; handleDelete: () => void; handleDuplicate: () => void; + handleExport: () => void; disableFunctions: boolean; }; @@ -15,6 +16,7 @@ const HeaderComponent = ({ handleSelectAll, handleDelete, handleDuplicate, + handleExport, disableFunctions, }: HeaderComponentProps) => { const [shouldSelectAll, setShouldSelectAll] = useState(true); @@ -49,6 +51,24 @@ const HeaderComponent = ({
+
+ Select items to export + ) : ( + Export selected items + ) + } + > + + +
From 22248d91040ba5f99b1a8058797c7f96df342f42 Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Thu, 6 Jun 2024 14:39:33 -0300 Subject: [PATCH 04/31] Fixed naming of errors --- .../pages/MainPage/components/componentsComponent/index.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/frontend/src/pages/MainPage/components/componentsComponent/index.tsx b/src/frontend/src/pages/MainPage/components/componentsComponent/index.tsx index 3e167db13..5bd536e8d 100644 --- a/src/frontend/src/pages/MainPage/components/componentsComponent/index.tsx +++ b/src/frontend/src/pages/MainPage/components/componentsComponent/index.tsx @@ -131,7 +131,7 @@ export default function ComponentsComponent({ setOpenDelete(true); } else if (action === "duplicate") { handleDuplicate(); - } else if (action === "exprot") { + } else if (action === "export") { handleExport(); } }; @@ -174,6 +174,7 @@ export default function ComponentsComponent({ selectedFlow!.description, ); }); + setSuccessData({ title: "Flows exported successfully" }); }; const handleDeleteMultiple = () => { @@ -185,7 +186,7 @@ export default function ComponentsComponent({ getFolderById(folderId ? folderId : myCollectionId); } setSuccessData({ - title: "Selected items deleted successfully!", + title: "Selected items deleted successfully", }); }) .catch(() => { From a96b08472f46526b9b1c4a8a504f2a4539ee876b Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Thu, 6 Jun 2024 14:42:50 -0300 Subject: [PATCH 05/31] Fixed buttons not using ShadCN buttons on header of components section --- .../components/headerComponent/index.tsx | 28 +++++++++++++++---- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/frontend/src/pages/MainPage/components/headerComponent/index.tsx b/src/frontend/src/pages/MainPage/components/headerComponent/index.tsx index 756fda03c..114816a91 100644 --- a/src/frontend/src/pages/MainPage/components/headerComponent/index.tsx +++ b/src/frontend/src/pages/MainPage/components/headerComponent/index.tsx @@ -3,6 +3,7 @@ import IconComponent from "../../../../components/genericIconComponent"; import ShadTooltip from "../../../../components/shadTooltipComponent"; import { Checkbox } from "../../../../components/ui/checkbox"; import { cn } from "../../../../utils/utils"; +import { Button } from "../../../../components/ui/button"; type HeaderComponentProps = { handleSelectAll: (select) => void; @@ -61,12 +62,17 @@ const HeaderComponent = ({ ) } > - +
@@ -79,12 +85,17 @@ const HeaderComponent = ({ ) } > - +
@@ -97,7 +108,12 @@ const HeaderComponent = ({ ) } > - +
From 9c91f4056aadec354d02729c1fa1fa72f496f41a Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Thu, 6 Jun 2024 14:43:04 -0300 Subject: [PATCH 06/31] Fixed naming and position of alert on Export modal --- src/frontend/src/constants/constants.ts | 2 +- src/frontend/src/modals/exportModal/index.tsx | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/frontend/src/constants/constants.ts b/src/frontend/src/constants/constants.ts index d9ce00554..a113b3911 100644 --- a/src/frontend/src/constants/constants.ts +++ b/src/frontend/src/constants/constants.ts @@ -668,7 +668,7 @@ export const ZERO_NOTIFICATIONS = "No new notifications"; export const SUCCESS_BUILD = "Built sucessfully ✨"; export const ALERT_SAVE_WITH_API = - "Caution: Uncheck this box only removes API keys from fields specifically designated for API keys."; + "Caution: Unchecking this box only removes API keys from fields specifically designated for API keys."; export const SAVE_WITH_API_CHECKBOX = "Save with my API keys"; export const EDIT_TEXT_MODAL_TITLE = "Edit Text"; diff --git a/src/frontend/src/modals/exportModal/index.tsx b/src/frontend/src/modals/exportModal/index.tsx index a04891821..9cd81c123 100644 --- a/src/frontend/src/modals/exportModal/index.tsx +++ b/src/frontend/src/modals/exportModal/index.tsx @@ -45,7 +45,7 @@ const ExportModal = forwardRef( is_component: false, }, name!, - description + description, ); setNoticeData({ title: API_WARNING_NOTICE_ALERT, @@ -61,7 +61,7 @@ const ExportModal = forwardRef( is_component: false, }), name!, - description + description, ); setOpen(false); }} @@ -94,7 +94,7 @@ const ExportModal = forwardRef( {SAVE_WITH_API_CHECKBOX} - + {ALERT_SAVE_WITH_API} @@ -102,6 +102,6 @@ const ExportModal = forwardRef( ); - } + }, ); export default ExportModal; From fe9dcdf424efb3732ee520f6b85072a304508bb3 Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Thu, 6 Jun 2024 14:59:10 -0300 Subject: [PATCH 07/31] Fixed select all classes --- .../components/headerComponent/index.tsx | 30 ++++++++----------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/src/frontend/src/pages/MainPage/components/headerComponent/index.tsx b/src/frontend/src/pages/MainPage/components/headerComponent/index.tsx index 114816a91..dc7143198 100644 --- a/src/frontend/src/pages/MainPage/components/headerComponent/index.tsx +++ b/src/frontend/src/pages/MainPage/components/headerComponent/index.tsx @@ -31,25 +31,19 @@ const HeaderComponent = ({ <>
- -
From ec240072e77a95244c2ba2990a097165a5e8dbe8 Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Thu, 6 Jun 2024 15:03:10 -0300 Subject: [PATCH 08/31] Added Upload Flow button to main page --- .../components/headerComponent/index.tsx | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/frontend/src/pages/MainPage/components/headerComponent/index.tsx b/src/frontend/src/pages/MainPage/components/headerComponent/index.tsx index dc7143198..e5145fd83 100644 --- a/src/frontend/src/pages/MainPage/components/headerComponent/index.tsx +++ b/src/frontend/src/pages/MainPage/components/headerComponent/index.tsx @@ -1,5 +1,7 @@ import { useState } from "react"; -import IconComponent from "../../../../components/genericIconComponent"; +import IconComponent, { + ForwardedIconComponent, +} from "../../../../components/genericIconComponent"; import ShadTooltip from "../../../../components/shadTooltipComponent"; import { Checkbox } from "../../../../components/ui/checkbox"; import { cn } from "../../../../utils/utils"; @@ -30,7 +32,19 @@ const HeaderComponent = ({ return ( <>
-
+
+ + {allFlows?.length > 0 && ( + handleSelectOptionsChange("delete")} + handleSelectAll={handleSelectAll} + handleDuplicate={() => handleSelectOptionsChange("duplicate")} + handleExport={() => handleSelectOptionsChange("export")} + disableFunctions={!(selectedFlowsComponentsCards?.length > 0)} + /> + )} +
{ return ( <> -
+
diff --git a/src/frontend/src/pages/MainPage/components/headerComponent/index.tsx b/src/frontend/src/pages/MainPage/components/headerComponent/index.tsx index a4fd7cfb4..b52fe8ad0 100644 --- a/src/frontend/src/pages/MainPage/components/headerComponent/index.tsx +++ b/src/frontend/src/pages/MainPage/components/headerComponent/index.tsx @@ -12,7 +12,6 @@ type HeaderComponentProps = { handleDelete: () => void; handleDuplicate: () => void; handleExport: () => void; - handleImport: () => void; disableFunctions: boolean; }; @@ -21,7 +20,6 @@ const HeaderComponent = ({ handleDelete, handleDuplicate, handleExport, - handleImport, disableFunctions, }: HeaderComponentProps) => { const [shouldSelectAll, setShouldSelectAll] = useState(true); @@ -33,20 +31,8 @@ const HeaderComponent = ({ return ( <> -
-
- +
+
-
+
Date: Thu, 6 Jun 2024 17:37:59 -0300 Subject: [PATCH 13/31] chore: Update import paths for GenericNode and getFieldTitle --- .../src/pages/FlowPage/components/PageComponent/index.tsx | 2 +- src/frontend/src/utils/reactflowUtils.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx index eb94a7fde..9d1db186f 100644 --- a/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx +++ b/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx @@ -11,13 +11,13 @@ import ReactFlow, { SelectionDragHandler, updateEdge, } from "reactflow"; -import GenericNode from "../../../../CustomNodes/GenericNode"; import { INVALID_SELECTION_ERROR_ALERT, UPLOAD_ALERT_LIST, UPLOAD_ERROR_ALERT, WRONG_FILE_ERROR_ALERT, } from "../../../../constants/alerts_constants"; +import GenericNode from "../../../../customNodes/GenericNode"; import useAlertStore from "../../../../stores/alertStore"; import useFlowStore from "../../../../stores/flowStore"; import useFlowsManagerStore from "../../../../stores/flowsManagerStore"; diff --git a/src/frontend/src/utils/reactflowUtils.ts b/src/frontend/src/utils/reactflowUtils.ts index 62e87c50b..d1f960017 100644 --- a/src/frontend/src/utils/reactflowUtils.ts +++ b/src/frontend/src/utils/reactflowUtils.ts @@ -8,7 +8,6 @@ import { XYPosition, } from "reactflow"; import ShortUniqueId from "short-unique-id"; -import getFieldTitle from "../CustomNodes/utils/get-field-title"; import { INPUT_TYPES, LANGFLOW_SUPPORTED_TYPES, @@ -17,6 +16,7 @@ import { specialCharsRegex, } from "../constants/constants"; import { downloadFlowsFromDatabase } from "../controllers/API"; +import getFieldTitle from "../customNodes/utils/get-field-title"; import { DESCRIPTIONS } from "../flow_constants"; import { APIClassType, From e1846167df1a2781e9c8d5a2fb1825ea4b84939b Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Thu, 6 Jun 2024 17:42:53 -0300 Subject: [PATCH 14/31] Removed Upload Flows from page --- .../components/componentsComponent/index.tsx | 12 ------------ .../MainPage/components/headerComponent/index.tsx | 4 ++-- src/frontend/src/utils/styleUtils.ts | 2 ++ 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/src/frontend/src/pages/MainPage/components/componentsComponent/index.tsx b/src/frontend/src/pages/MainPage/components/componentsComponent/index.tsx index 62ec3b246..fa5524891 100644 --- a/src/frontend/src/pages/MainPage/components/componentsComponent/index.tsx +++ b/src/frontend/src/pages/MainPage/components/componentsComponent/index.tsx @@ -270,18 +270,6 @@ export default function ComponentsComponent({ return ( <>
- {allFlows?.length > 0 && ( handleSelectOptionsChange("delete")} diff --git a/src/frontend/src/pages/MainPage/components/headerComponent/index.tsx b/src/frontend/src/pages/MainPage/components/headerComponent/index.tsx index ea45bb5aa..527c8d423 100644 --- a/src/frontend/src/pages/MainPage/components/headerComponent/index.tsx +++ b/src/frontend/src/pages/MainPage/components/headerComponent/index.tsx @@ -31,7 +31,7 @@ const HeaderComponent = ({ return ( <> -
+
-
+
Date: Thu, 6 Jun 2024 17:46:38 -0300 Subject: [PATCH 15/31] Fixed Messages icon --- src/frontend/src/pages/SettingsPage/index.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/frontend/src/pages/SettingsPage/index.tsx b/src/frontend/src/pages/SettingsPage/index.tsx index d956f20f4..d5face8fa 100644 --- a/src/frontend/src/pages/SettingsPage/index.tsx +++ b/src/frontend/src/pages/SettingsPage/index.tsx @@ -8,7 +8,7 @@ import useFlowsManagerStore from "../../stores/flowsManagerStore"; export default function SettingsPage(): JSX.Element { const pathname = location.pathname; const setCurrentFlowId = useFlowsManagerStore( - (state) => state.setCurrentFlowId + (state) => state.setCurrentFlowId, ); useEffect(() => { setCurrentFlowId(""); @@ -59,7 +59,10 @@ export default function SettingsPage(): JSX.Element { title: "Messages", href: "/settings/messages", icon: ( - + ), }, ]; From c8ce77bbf0d299e4efb4d935b437d39984d7d19a Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Thu, 6 Jun 2024 17:49:20 -0300 Subject: [PATCH 16/31] Fixed padding from Settings page outlet --- src/frontend/src/pages/SettingsPage/index.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/frontend/src/pages/SettingsPage/index.tsx b/src/frontend/src/pages/SettingsPage/index.tsx index d5face8fa..d201d2596 100644 --- a/src/frontend/src/pages/SettingsPage/index.tsx +++ b/src/frontend/src/pages/SettingsPage/index.tsx @@ -75,8 +75,10 @@ export default function SettingsPage(): JSX.Element { -
- +
+
+ +
From 2558786851a861cb3fb95540447e66e5c17b5a2f Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Thu, 6 Jun 2024 17:49:53 -0300 Subject: [PATCH 17/31] Fixed padding from Messages page --- .../src/pages/SettingsPage/pages/messagesPage/index.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/frontend/src/pages/SettingsPage/pages/messagesPage/index.tsx b/src/frontend/src/pages/SettingsPage/pages/messagesPage/index.tsx index 2fff6f360..c46910fd1 100644 --- a/src/frontend/src/pages/SettingsPage/pages/messagesPage/index.tsx +++ b/src/frontend/src/pages/SettingsPage/pages/messagesPage/index.tsx @@ -27,7 +27,7 @@ export default function MessagesPage() { setSelectedRows, setSuccessData, setErrorData, - selectedRows + selectedRows, ); const { handleUpdate } = useUpdateMessage(setSuccessData, setErrorData); @@ -52,7 +52,7 @@ export default function MessagesPage() { handleRemoveMessages={handleRemoveMessages} /> -
+
{ setSelectedRows( - event.api.getSelectedRows().map((row) => row.index) + event.api.getSelectedRows().map((row) => row.index), ); }} rowSelection="multiple" From cfd4f2a732a29fe1cc066db709a19bed3b489471 Mon Sep 17 00:00:00 2001 From: ogabrielluiz Date: Thu, 6 Jun 2024 17:55:52 -0300 Subject: [PATCH 18/31] chore: Update import paths for GenericNode and getFieldTitle --- .github/workflows/pre-release.yml | 4 ++++ .../src/pages/FlowPage/components/PageComponent/index.tsx | 2 +- src/frontend/src/utils/reactflowUtils.ts | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release.yml index 8cb0bc90e..286a7a921 100644 --- a/.github/workflows/pre-release.yml +++ b/.github/workflows/pre-release.yml @@ -35,6 +35,10 @@ jobs: with: python-version: "3.10" cache: "poetry" + - name: Set up Nodejs 20 + uses: actions/setup-node@v4 + with: + node-version: "20" - name: Check Version id: check-version run: | diff --git a/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx index 9d1db186f..eb94a7fde 100644 --- a/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx +++ b/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx @@ -11,13 +11,13 @@ import ReactFlow, { SelectionDragHandler, updateEdge, } from "reactflow"; +import GenericNode from "../../../../CustomNodes/GenericNode"; import { INVALID_SELECTION_ERROR_ALERT, UPLOAD_ALERT_LIST, UPLOAD_ERROR_ALERT, WRONG_FILE_ERROR_ALERT, } from "../../../../constants/alerts_constants"; -import GenericNode from "../../../../customNodes/GenericNode"; import useAlertStore from "../../../../stores/alertStore"; import useFlowStore from "../../../../stores/flowStore"; import useFlowsManagerStore from "../../../../stores/flowsManagerStore"; diff --git a/src/frontend/src/utils/reactflowUtils.ts b/src/frontend/src/utils/reactflowUtils.ts index d1f960017..62e87c50b 100644 --- a/src/frontend/src/utils/reactflowUtils.ts +++ b/src/frontend/src/utils/reactflowUtils.ts @@ -8,6 +8,7 @@ import { XYPosition, } from "reactflow"; import ShortUniqueId from "short-unique-id"; +import getFieldTitle from "../CustomNodes/utils/get-field-title"; import { INPUT_TYPES, LANGFLOW_SUPPORTED_TYPES, @@ -16,7 +17,6 @@ import { specialCharsRegex, } from "../constants/constants"; import { downloadFlowsFromDatabase } from "../controllers/API"; -import getFieldTitle from "../customNodes/utils/get-field-title"; import { DESCRIPTIONS } from "../flow_constants"; import { APIClassType, From e994b1b6498b20fc4dd2937ada9e7be319bc9522 Mon Sep 17 00:00:00 2001 From: ogabrielluiz Date: Thu, 6 Jun 2024 18:02:29 -0300 Subject: [PATCH 19/31] rename folder --- .../genericNode/components/parameterComponent/constants.ts | 0 .../genericNode/components/parameterComponent/index.tsx | 0 .../genericNode/components/tooltipRenderComponent/index.tsx | 0 .../src/{customNodes => CustomNodes}/genericNode/index.tsx | 0 .../hooks/use-fetch-data-on-mount.tsx | 0 .../{customNodes => CustomNodes}/hooks/use-handle-new-value.tsx | 0 .../{customNodes => CustomNodes}/hooks/use-handle-node-class.tsx | 0 .../hooks/use-handle-refresh-buttons.tsx | 0 .../src/{customNodes => CustomNodes}/utils/get-field-title.tsx | 0 .../src/{customNodes => CustomNodes}/utils/sort-fields.tsx | 0 10 files changed, 0 insertions(+), 0 deletions(-) rename src/frontend/src/{customNodes => CustomNodes}/genericNode/components/parameterComponent/constants.ts (100%) rename src/frontend/src/{customNodes => CustomNodes}/genericNode/components/parameterComponent/index.tsx (100%) rename src/frontend/src/{customNodes => CustomNodes}/genericNode/components/tooltipRenderComponent/index.tsx (100%) rename src/frontend/src/{customNodes => CustomNodes}/genericNode/index.tsx (100%) rename src/frontend/src/{customNodes => CustomNodes}/hooks/use-fetch-data-on-mount.tsx (100%) rename src/frontend/src/{customNodes => CustomNodes}/hooks/use-handle-new-value.tsx (100%) rename src/frontend/src/{customNodes => CustomNodes}/hooks/use-handle-node-class.tsx (100%) rename src/frontend/src/{customNodes => CustomNodes}/hooks/use-handle-refresh-buttons.tsx (100%) rename src/frontend/src/{customNodes => CustomNodes}/utils/get-field-title.tsx (100%) rename src/frontend/src/{customNodes => CustomNodes}/utils/sort-fields.tsx (100%) diff --git a/src/frontend/src/customNodes/genericNode/components/parameterComponent/constants.ts b/src/frontend/src/CustomNodes/genericNode/components/parameterComponent/constants.ts similarity index 100% rename from src/frontend/src/customNodes/genericNode/components/parameterComponent/constants.ts rename to src/frontend/src/CustomNodes/genericNode/components/parameterComponent/constants.ts diff --git a/src/frontend/src/customNodes/genericNode/components/parameterComponent/index.tsx b/src/frontend/src/CustomNodes/genericNode/components/parameterComponent/index.tsx similarity index 100% rename from src/frontend/src/customNodes/genericNode/components/parameterComponent/index.tsx rename to src/frontend/src/CustomNodes/genericNode/components/parameterComponent/index.tsx diff --git a/src/frontend/src/customNodes/genericNode/components/tooltipRenderComponent/index.tsx b/src/frontend/src/CustomNodes/genericNode/components/tooltipRenderComponent/index.tsx similarity index 100% rename from src/frontend/src/customNodes/genericNode/components/tooltipRenderComponent/index.tsx rename to src/frontend/src/CustomNodes/genericNode/components/tooltipRenderComponent/index.tsx diff --git a/src/frontend/src/customNodes/genericNode/index.tsx b/src/frontend/src/CustomNodes/genericNode/index.tsx similarity index 100% rename from src/frontend/src/customNodes/genericNode/index.tsx rename to src/frontend/src/CustomNodes/genericNode/index.tsx diff --git a/src/frontend/src/customNodes/hooks/use-fetch-data-on-mount.tsx b/src/frontend/src/CustomNodes/hooks/use-fetch-data-on-mount.tsx similarity index 100% rename from src/frontend/src/customNodes/hooks/use-fetch-data-on-mount.tsx rename to src/frontend/src/CustomNodes/hooks/use-fetch-data-on-mount.tsx diff --git a/src/frontend/src/customNodes/hooks/use-handle-new-value.tsx b/src/frontend/src/CustomNodes/hooks/use-handle-new-value.tsx similarity index 100% rename from src/frontend/src/customNodes/hooks/use-handle-new-value.tsx rename to src/frontend/src/CustomNodes/hooks/use-handle-new-value.tsx diff --git a/src/frontend/src/customNodes/hooks/use-handle-node-class.tsx b/src/frontend/src/CustomNodes/hooks/use-handle-node-class.tsx similarity index 100% rename from src/frontend/src/customNodes/hooks/use-handle-node-class.tsx rename to src/frontend/src/CustomNodes/hooks/use-handle-node-class.tsx diff --git a/src/frontend/src/customNodes/hooks/use-handle-refresh-buttons.tsx b/src/frontend/src/CustomNodes/hooks/use-handle-refresh-buttons.tsx similarity index 100% rename from src/frontend/src/customNodes/hooks/use-handle-refresh-buttons.tsx rename to src/frontend/src/CustomNodes/hooks/use-handle-refresh-buttons.tsx diff --git a/src/frontend/src/customNodes/utils/get-field-title.tsx b/src/frontend/src/CustomNodes/utils/get-field-title.tsx similarity index 100% rename from src/frontend/src/customNodes/utils/get-field-title.tsx rename to src/frontend/src/CustomNodes/utils/get-field-title.tsx diff --git a/src/frontend/src/customNodes/utils/sort-fields.tsx b/src/frontend/src/CustomNodes/utils/sort-fields.tsx similarity index 100% rename from src/frontend/src/customNodes/utils/sort-fields.tsx rename to src/frontend/src/CustomNodes/utils/sort-fields.tsx From 0f82fdc77be24172552ec7009d7c3a1eba7b7f74 Mon Sep 17 00:00:00 2001 From: ogabrielluiz Date: Thu, 6 Jun 2024 18:23:38 -0300 Subject: [PATCH 20/31] Remove folder --- .../parameterComponent/constants.ts | 1 - .../components/parameterComponent/index.tsx | 584 ------------ .../tooltipRenderComponent/index.tsx | 91 -- .../src/CustomNodes/genericNode/index.tsx | 849 ------------------ .../hooks/use-fetch-data-on-mount.tsx | 54 -- .../hooks/use-handle-new-value.tsx | 76 -- .../hooks/use-handle-node-class.tsx | 40 - .../hooks/use-handle-refresh-buttons.tsx | 39 - .../src/CustomNodes/utils/get-field-title.tsx | 10 - .../src/CustomNodes/utils/sort-fields.tsx | 40 - 10 files changed, 1784 deletions(-) delete mode 100644 src/frontend/src/CustomNodes/genericNode/components/parameterComponent/constants.ts delete mode 100644 src/frontend/src/CustomNodes/genericNode/components/parameterComponent/index.tsx delete mode 100644 src/frontend/src/CustomNodes/genericNode/components/tooltipRenderComponent/index.tsx delete mode 100644 src/frontend/src/CustomNodes/genericNode/index.tsx delete mode 100644 src/frontend/src/CustomNodes/hooks/use-fetch-data-on-mount.tsx delete mode 100644 src/frontend/src/CustomNodes/hooks/use-handle-new-value.tsx delete mode 100644 src/frontend/src/CustomNodes/hooks/use-handle-node-class.tsx delete mode 100644 src/frontend/src/CustomNodes/hooks/use-handle-refresh-buttons.tsx delete mode 100644 src/frontend/src/CustomNodes/utils/get-field-title.tsx delete mode 100644 src/frontend/src/CustomNodes/utils/sort-fields.tsx diff --git a/src/frontend/src/CustomNodes/genericNode/components/parameterComponent/constants.ts b/src/frontend/src/CustomNodes/genericNode/components/parameterComponent/constants.ts deleted file mode 100644 index 58cb45587..000000000 --- a/src/frontend/src/CustomNodes/genericNode/components/parameterComponent/constants.ts +++ /dev/null @@ -1 +0,0 @@ -export const TEXT_FIELD_TYPES: string[] = ["str", "SecretStr"]; diff --git a/src/frontend/src/CustomNodes/genericNode/components/parameterComponent/index.tsx b/src/frontend/src/CustomNodes/genericNode/components/parameterComponent/index.tsx deleted file mode 100644 index dfa0a6812..000000000 --- a/src/frontend/src/CustomNodes/genericNode/components/parameterComponent/index.tsx +++ /dev/null @@ -1,584 +0,0 @@ -import { cloneDeep } from "lodash"; -import { ReactNode, useEffect, useRef, useState } from "react"; -import { Handle, Position, useUpdateNodeInternals } from "reactflow"; -import CodeAreaComponent from "../../../../components/codeAreaComponent"; -import DictComponent from "../../../../components/dictComponent"; -import Dropdown from "../../../../components/dropdownComponent"; -import FloatComponent from "../../../../components/floatComponent"; -import { default as IconComponent } from "../../../../components/genericIconComponent"; -import InputFileComponent from "../../../../components/inputFileComponent"; -import InputGlobalComponent from "../../../../components/inputGlobalComponent"; -import InputListComponent from "../../../../components/inputListComponent"; -import IntComponent from "../../../../components/intComponent"; -import KeypairListComponent from "../../../../components/keypairListComponent"; -import PromptAreaComponent from "../../../../components/promptComponent"; -import ShadTooltip from "../../../../components/shadTooltipComponent"; -import TextAreaComponent from "../../../../components/textAreaComponent"; -import ToggleShadComponent from "../../../../components/toggleShadComponent"; -import { Button } from "../../../../components/ui/button"; -import { RefreshButton } from "../../../../components/ui/refreshButton"; -import { - LANGFLOW_SUPPORTED_TYPES, - TOOLTIP_EMPTY, -} from "../../../../constants/constants"; -import { Case } from "../../../../shared/components/caseComponent"; -import useAlertStore from "../../../../stores/alertStore"; -import useFlowStore from "../../../../stores/flowStore"; -import useFlowsManagerStore from "../../../../stores/flowsManagerStore"; -import { useTypesStore } from "../../../../stores/typesStore"; -import { APIClassType } from "../../../../types/api"; -import { ParameterComponentType } from "../../../../types/components"; -import { - debouncedHandleUpdateValues, - handleUpdateValues, -} from "../../../../utils/parameterUtils"; -import { - convertObjToArray, - convertValuesToNumbers, - hasDuplicateKeys, - isValidConnection, - scapedJSONStringfy, -} from "../../../../utils/reactflowUtils"; -import { nodeColors } from "../../../../utils/styleUtils"; -import { classNames, groupByFamily } from "../../../../utils/utils"; -import useFetchDataOnMount from "../../../hooks/use-fetch-data-on-mount"; -import useHandleOnNewValue from "../../../hooks/use-handle-new-value"; -import useHandleNodeClass from "../../../hooks/use-handle-node-class"; -import useHandleRefreshButtonPress from "../../../hooks/use-handle-refresh-buttons"; -import TooltipRenderComponent from "../tooltipRenderComponent"; -import { TEXT_FIELD_TYPES } from "./constants"; - -export default function ParameterComponent({ - left, - id, - data, - tooltipTitle, - title, - color, - type, - name = "", - required = false, - optionalHandle = null, - info = "", - proxy, - showNode, - index = "", -}: ParameterComponentType): JSX.Element { - const ref = useRef(null); - const refHtml = useRef(null); - const infoHtml = useRef(null); - const currentFlow = useFlowsManagerStore((state) => state.currentFlow); - const nodes = useFlowStore((state) => state.nodes); - const edges = useFlowStore((state) => state.edges); - const setNode = useFlowStore((state) => state.setNode); - const myData = useTypesStore((state) => state.data); - const takeSnapshot = useFlowsManagerStore((state) => state.takeSnapshot); - const [isLoading, setIsLoading] = useState(false); - const updateNodeInternals = useUpdateNodeInternals(); - const [errorDuplicateKey, setErrorDuplicateKey] = useState(false); - const flow = currentFlow?.data?.nodes ?? null; - const groupedEdge = useRef(null); - const setFilterEdge = useFlowStore((state) => state.setFilterEdge); - - const { handleOnNewValue: handleOnNewValueHook } = useHandleOnNewValue( - data, - name, - takeSnapshot, - handleUpdateValues, - debouncedHandleUpdateValues, - setNode, - renderTooltips, - setIsLoading - ); - - const { handleNodeClass: handleNodeClassHook } = useHandleNodeClass( - data, - name, - takeSnapshot, - setNode, - updateNodeInternals, - renderTooltips - ); - - const { handleRefreshButtonPress: handleRefreshButtonPressHook } = - useHandleRefreshButtonPress(setIsLoading, setNode, renderTooltips); - - let disabled = - edges.some( - (edge) => - edge.targetHandle === scapedJSONStringfy(proxy ? { ...id, proxy } : id) - ) ?? false; - - const handleRefreshButtonPress = async (name, data) => { - handleRefreshButtonPressHook(name, data); - }; - - useFetchDataOnMount( - data, - name, - handleUpdateValues, - setNode, - renderTooltips, - setIsLoading - ); - - const handleOnNewValue = async ( - newValue: string | string[] | boolean | Object[], - skipSnapshot: boolean | undefined = false - ): Promise => { - handleOnNewValueHook(newValue, skipSnapshot); - }; - - const handleNodeClass = (newNodeClass: APIClassType, code?: string): void => { - handleNodeClassHook(newNodeClass, code); - }; - - useEffect(() => { - // @ts-ignore - infoHtml.current = ( -
- {info.split("\n").map((line, index) => ( -

- {line} -

- ))} -
- ); - }, [info]); - - function renderTooltips() { - let groupedObj: any = groupByFamily(myData, tooltipTitle!, left, flow!); - groupedEdge.current = groupedObj; - - if (groupedObj && groupedObj.length > 0) { - //@ts-ignore - refHtml.current = groupedObj.map((item, index) => { - return ; - }); - } else { - //@ts-ignore - refHtml.current = ( - {TOOLTIP_EMPTY} - ); - } - } - - // If optionalHandle is an empty list, then it is not an optional handle - if (optionalHandle && optionalHandle.length === 0) { - optionalHandle = null; - } - - useEffect(() => { - renderTooltips(); - }, [tooltipTitle, flow]); - - return !showNode ? ( - left && LANGFLOW_SUPPORTED_TYPES.has(type ?? "") && !optionalHandle ? ( - <> - ) : ( - - ) - ) : ( - - ); -} diff --git a/src/frontend/src/CustomNodes/genericNode/components/tooltipRenderComponent/index.tsx b/src/frontend/src/CustomNodes/genericNode/components/tooltipRenderComponent/index.tsx deleted file mode 100644 index c76bc7293..000000000 --- a/src/frontend/src/CustomNodes/genericNode/components/tooltipRenderComponent/index.tsx +++ /dev/null @@ -1,91 +0,0 @@ -import React from "react"; -import { - INPUT_HANDLER_HOVER, - OUTPUT_HANDLER_HOVER, -} from "../../../../constants/constants"; -import { - nodeColors, - nodeIconsLucide, - nodeNames, -} from "../../../../utils/styleUtils"; -import { classNames } from "../../../../utils/utils"; - -const TooltipRenderComponent = ({ item, index, left }) => { - const Icon = nodeIconsLucide[item.family] ?? nodeIconsLucide["unknown"]; - - return ( -
- {index === 0 && ( - {left ? INPUT_HANDLER_HOVER : OUTPUT_HANDLER_HOVER} - )} - 0 ? "mt-2 flex items-center" : "mt-3 flex items-center" - )} - > -
- -
- - {nodeNames[item.family] ?? "Other"}{" "} - {item?.display_name && item?.display_name?.length > 0 ? ( - - {" "} - {item.display_name === "" ? "" : " - "} - {item.display_name.split(", ").length > 2 - ? item.display_name.split(", ").map((el, index) => ( - - - {index === item.display_name.split(", ").length - 1 - ? el - : (el += `, `)} - - - )) - : item.display_name} - - ) : ( - - {" "} - {item.type === "" ? "" : " - "} - {item.type.split(", ").length > 2 - ? item.type.split(", ").map((el, index) => ( - - - {index === item.type.split(", ").length - 1 - ? el - : (el += `, `)} - - - )) - : item.type} - - )} - -
-
- ); -}; - -export default TooltipRenderComponent; diff --git a/src/frontend/src/CustomNodes/genericNode/index.tsx b/src/frontend/src/CustomNodes/genericNode/index.tsx deleted file mode 100644 index ba0d1c9a6..000000000 --- a/src/frontend/src/CustomNodes/genericNode/index.tsx +++ /dev/null @@ -1,849 +0,0 @@ -import emojiRegex from "emoji-regex"; -import { cloneDeep } from "lodash"; -import { useCallback, useEffect, useMemo, useState } from "react"; -import { NodeToolbar, useUpdateNodeInternals } from "reactflow"; -import IconComponent from "../../components/genericIconComponent"; -import InputComponent from "../../components/inputComponent"; -import ShadTooltip from "../../components/shadTooltipComponent"; -import { Button } from "../../components/ui/button"; -import Checkmark from "../../components/ui/checkmark"; -import Loading from "../../components/ui/loading"; -import { Textarea } from "../../components/ui/textarea"; -import Xmark from "../../components/ui/xmark"; -import { - RUN_TIMESTAMP_PREFIX, - STATUS_BUILD, - STATUS_BUILDING, -} from "../../constants/constants"; -import { BuildStatus } from "../../constants/enums"; -import NodeToolbarComponent from "../../pages/FlowPage/components/nodeToolbarComponent"; -import useAlertStore from "../../stores/alertStore"; -import { useDarkStore } from "../../stores/darkStore"; -import useFlowStore from "../../stores/flowStore"; -import useFlowsManagerStore from "../../stores/flowsManagerStore"; -import { useTypesStore } from "../../stores/typesStore"; -import { APIClassType } from "../../types/api"; -import { validationStatusType } from "../../types/components"; -import { NodeDataType } from "../../types/flow"; -import { handleKeyDown, scapedJSONStringfy } from "../../utils/reactflowUtils"; -import { nodeColors, nodeIconsLucide } from "../../utils/styleUtils"; -import { classNames, cn } from "../../utils/utils"; -import getFieldTitle from "../utils/get-field-title"; -import sortFields from "../utils/sort-fields"; -import ParameterComponent from "./components/parameterComponent"; - -export default function GenericNode({ - data, - xPos, - yPos, - selected, -}: { - data: NodeDataType; - selected: boolean; - xPos: number; - yPos: number; -}): JSX.Element { - const types = useTypesStore((state) => state.types); - const templates = useTypesStore((state) => state.templates); - const deleteNode = useFlowStore((state) => state.deleteNode); - const flowPool = useFlowStore((state) => state.flowPool); - const buildFlow = useFlowStore((state) => state.buildFlow); - const setNode = useFlowStore((state) => state.setNode); - const updateNodeInternals = useUpdateNodeInternals(); - const setErrorData = useAlertStore((state) => state.setErrorData); - const name = nodeIconsLucide[data.type] ? data.type : types[data.type]; - const [inputName, setInputName] = useState(false); - const [nodeName, setNodeName] = useState(data.node!.display_name); - const [inputDescription, setInputDescription] = useState(false); - const [nodeDescription, setNodeDescription] = useState( - data.node?.description! - ); - const [isOutdated, setIsOutdated] = useState(false); - const buildStatus = useFlowStore( - (state) => state.flowBuildStatus[data.id]?.status - ); - const lastRunTime = useFlowStore( - (state) => state.flowBuildStatus[data.id]?.timestamp - ); - const [validationStatus, setValidationStatus] = - useState(null); - const [handles, setHandles] = useState(0); - - const [validationString, setValidationString] = useState(""); - - const takeSnapshot = useFlowsManagerStore((state) => state.takeSnapshot); - - useEffect(() => { - // This one should run only once - // first check if data.type in NATIVE_CATEGORIES - // if not return - if (!data.node?.template?.code?.value) return; - const thisNodeTemplate = templates[data.type]?.template; - // if the template does not have a code key - // return - if (!thisNodeTemplate?.code) return; - const currentCode = thisNodeTemplate.code?.value; - const thisNodesCode = data.node!.template?.code?.value; - const componentsToIgnore = ["Custom Component"]; - if ( - currentCode !== thisNodesCode && - !componentsToIgnore.includes(data.node!.display_name) - ) { - setIsOutdated(true); - } else { - setIsOutdated(false); - } - // template.code can be undefined - }, [data.node?.template?.code?.value]); - - const updateNodeCode = useCallback( - (newNodeClass: APIClassType, code: string, name: string) => { - setNode(data.id, (oldNode) => { - let newNode = cloneDeep(oldNode); - - newNode.data = { - ...newNode.data, - node: newNodeClass, - description: newNodeClass.description ?? data.node!.description, - display_name: newNodeClass.display_name ?? data.node!.display_name, - }; - - newNode.data.node.template[name].value = code; - setIsOutdated(false); - - return newNode; - }); - - updateNodeInternals(data.id); - }, - [data.id, data.node, setNode, setIsOutdated] - ); - - if (!data.node!.template) { - setErrorData({ - title: `Error in component ${data.node!.display_name}`, - list: [ - `The component ${data.node!.display_name} has no template.`, - `Please contact the developer of the component to fix this issue.`, - ], - }); - takeSnapshot(); - deleteNode(data.id); - } - - function countHandles(): void { - let count = Object.keys(data.node!.template) - .filter((templateField) => templateField.charAt(0) !== "_") - .map((templateCamp) => { - const { template } = data.node!; - if (template[templateCamp].input_types) return true; - if (!template[templateCamp].show) return false; - switch (template[templateCamp].type) { - case "str": - case "bool": - case "float": - case "code": - case "prompt": - case "file": - case "int": - return false; - default: - return true; - } - }) - .reduce((total, value) => total + (value ? 1 : 0), 0); - - setHandles(count); - } - useEffect(() => { - countHandles(); - }, [data, data.node]); - - useEffect(() => { - if (!selected) { - setInputName(false); - setInputDescription(false); - } - }, [selected]); - - // State for outline color - const isBuilding = useFlowStore((state) => state.isBuilding); - - // should be empty string if no duration - // else should be `Duration: ${duration}` - const getDurationString = (duration: number | undefined): string => { - if (duration === undefined) { - return ""; - } else { - return `${duration}`; - } - }; - const durationString = getDurationString(validationStatus?.data.duration); - - useEffect(() => { - setNodeDescription(data.node!.description); - }, [data.node!.description]); - - useEffect(() => { - setNodeName(data.node!.display_name); - }, [data.node!.display_name]); - - useEffect(() => { - const relevantData = - flowPool[data.id] && flowPool[data.id]?.length > 0 - ? flowPool[data.id][flowPool[data.id].length - 1] - : null; - if (relevantData) { - // Extract validation information from relevantData and update the validationStatus state - setValidationStatus(relevantData); - } else { - setValidationStatus(null); - } - }, [flowPool[data.id], data.id]); - - useEffect(() => { - if (validationStatus?.params) { - // if it is not a string turn it into a string - let newValidationString = validationStatus.params; - if (typeof newValidationString !== "string") { - newValidationString = JSON.stringify(validationStatus.params); - } - - setValidationString(newValidationString); - } - }, [validationStatus, validationStatus?.params]); - - const [showNode, setShowNode] = useState(data.showNode ?? true); - - useEffect(() => { - setShowNode(data.showNode ?? true); - }, [data.showNode]); - - const nameEditable = true; - - const isEmoji = emojiRegex().test(data?.node?.icon!); - - const iconNodeRender = useCallback(() => { - const iconElement = data?.node?.icon; - const iconColor = nodeColors[types[data.type]]; - const iconName = - iconElement || (data.node?.flow ? "group_components" : name); - const iconClassName = `generic-node-icon ${ - !showNode ? " absolute inset-x-6 h-12 w-12 " : "" - }`; - if (iconElement && isEmoji) { - return nodeIconFragment(iconElement); - } else { - return checkNodeIconFragment(iconColor, iconName, iconClassName); - } - }, [data, isEmoji, name, showNode]); - - const nodeIconFragment = (icon) => { - return {icon}; - }; - - const checkNodeIconFragment = (iconColor, iconName, iconClassName) => { - return ( - - ); - }; - - const isDark = useDarkStore((state) => state.dark); - const renderIconStatus = ( - buildStatus: BuildStatus | undefined, - validationStatus: validationStatusType | null - ) => { - if (buildStatus === BuildStatus.BUILDING) { - return ; - } else { - return ( - <> - - {validationStatus && validationStatus.valid ? ( - - ) : validationStatus && - !validationStatus.valid && - buildStatus === BuildStatus.INACTIVE ? ( - - ) : buildStatus === BuildStatus.ERROR || - (validationStatus && !validationStatus.valid) ? ( - - ) : ( - - )} - - ); - } - }; - const getSpecificClassFromBuildStatus = ( - buildStatus: BuildStatus | undefined, - validationStatus: validationStatusType | null - ) => { - let isInvalid = validationStatus && !validationStatus.valid; - - if (buildStatus === BuildStatus.INACTIVE) { - // INACTIVE should have its own class - return "inactive-status"; - } - if ( - (buildStatus === BuildStatus.BUILT && isInvalid) || - buildStatus === BuildStatus.ERROR - ) { - return isDark ? "built-invalid-status-dark" : "built-invalid-status"; - } else if (buildStatus === BuildStatus.BUILDING) { - return "building-status"; - } else { - return ""; - } - }; - - const getNodeBorderClassName = ( - selected: boolean, - showNode: boolean, - buildStatus: BuildStatus | undefined, - validationStatus: validationStatusType | null - ) => { - const specificClassFromBuildStatus = getSpecificClassFromBuildStatus( - buildStatus, - validationStatus - ); - - const baseBorderClass = getBaseBorderClass(selected); - const nodeSizeClass = getNodeSizeClass(showNode); - const names = classNames( - baseBorderClass, - nodeSizeClass, - "generic-node-div", - specificClassFromBuildStatus - ); - return names; - }; - - const getBaseBorderClass = (selected) => { - let className = selected ? "border border-ring" : "border"; - let frozenClass = selected ? "border-ring-frozen" : "border-frozen"; - return data.node?.frozen ? frozenClass : className; - }; - - const getNodeSizeClass = (showNode) => - showNode ? "w-96 rounded-lg" : "w-26 h-26 rounded-full"; - - const memoizedNodeToolbarComponent = useMemo(() => { - return ( - - { - takeSnapshot(); - deleteNode(id); - }} - setShowNode={(show) => { - setNode(data.id, (old) => ({ - ...old, - data: { ...old.data, showNode: show }, - })); - }} - setShowState={setShowNode} - numberOfHandles={handles} - showNode={showNode} - openAdvancedModal={false} - onCloseAdvancedModal={() => {}} - updateNodeCode={updateNodeCode} - isOutdated={isOutdated} - selected={selected} - /> - - ); - }, [ - data, - deleteNode, - takeSnapshot, - setNode, - setShowNode, - handles, - showNode, - updateNodeCode, - isOutdated, - selected, - ]); - return ( - <> - {memoizedNodeToolbarComponent} -
- {data.node?.beta && showNode && ( -
-
BETA
-
- )} -
-
-
- {iconNodeRender()} - {showNode && ( -
- {nameEditable && inputName ? ( -
- { - setInputName(false); - if (nodeName.trim() !== "") { - setNodeName(nodeName); - setNode(data.id, (old) => ({ - ...old, - data: { - ...old.data, - node: { - ...old.data.node, - display_name: nodeName, - }, - }, - })); - } else { - setNodeName(data.node!.display_name); - } - }} - value={nodeName} - onChange={setNodeName} - password={false} - blurOnEnter={true} - id={`input-title-${data.node?.display_name}`} - /> -
- ) : ( -
- -
{ - if (nameEditable) { - setInputName(true); - } - takeSnapshot(); - event.stopPropagation(); - event.preventDefault(); - }} - data-testid={"title-" + data.node?.display_name} - className="generic-node-tooltip-div cursor-text text-primary" - > - {data.node?.display_name} -
-
-
- )} -
- )} -
-
- {!showNode && ( - <> - {Object.keys(data.node!.template) - .filter((templateField) => templateField.charAt(0) !== "_") - .map( - (templateField: string, idx) => - data.node!.template[templateField].show && - !data.node!.template[templateField].advanced && ( - 0 - ? nodeColors[ - data.node?.template[templateField] - .input_types![ - data.node?.template[templateField] - .input_types!.length - 1 - ] - ] ?? - nodeColors[ - types[ - data.node?.template[templateField] - .input_types![ - data.node?.template[templateField] - .input_types!.length - 1 - ] - ] - ] - : nodeColors[ - data.node?.template[templateField].type! - ] ?? - nodeColors[ - types[ - data.node?.template[templateField].type! - ] - ] ?? - nodeColors.unknown - } - title={getFieldTitle( - data.node?.template!, - templateField - )} - info={data.node?.template[templateField].info} - name={templateField} - tooltipTitle={ - data.node?.template[ - templateField - ].input_types?.join("\n") ?? - data.node?.template[templateField].type - } - required={ - data.node!.template[templateField].required - } - id={{ - inputTypes: - data.node!.template[templateField].input_types, - type: data.node!.template[templateField].type, - id: data.id, - fieldName: templateField, - }} - left={true} - type={data.node?.template[templateField].type} - optionalHandle={ - data.node?.template[templateField].input_types - } - proxy={data.node?.template[templateField].proxy} - showNode={showNode} - /> - ) - )} - 0 - ? data.node.output_types.join(" | ") - : data.type - } - tooltipTitle={data.node?.base_classes.join("\n")} - id={{ - baseClasses: data.node!.base_classes, - id: data.id, - dataType: data.type, - }} - type={data.node?.base_classes.join("|")} - left={false} - showNode={showNode} - /> - - )} -
- {showNode && ( - {STATUS_BUILDING} - ) : !validationStatus ? ( - {STATUS_BUILD} - ) : ( -
-
- {lastRunTime && ( -
-
{RUN_TIMESTAMP_PREFIX}
-
- {lastRunTime} -
-
- )} -
-
-
Duration:
-
- {validationStatus?.data.duration} -
-
-
- - Output - -
- {validationString.split("\n").map((line, index) => ( -
- {line} -
- ))} -
-
- ) - } - side="bottom" - > - -
- )} -
-
- - {showNode && ( -
-
- {showNode && nameEditable && inputDescription ? ( -