From f0bbf127c51dea21f46bf8741704f2b3d5ed1790 Mon Sep 17 00:00:00 2001 From: Lucas Oliveira <62335616+lucaseduoli@users.noreply.github.com> Date: Wed, 7 Aug 2024 09:55:19 -0300 Subject: [PATCH] refactor: delete flow (#3208) * Removed unused function and fixed tags initial value * Added post save flow * Added update flow patch * removed unused import * created useAddFlow hook to substitute AddFlow function on flowsManager store * fixed post save flow to handle endpoint name as undefined * Fixed add flow hook to use post save flow mutation * removed unused line * changed addFlow to use hook in all components that use addFlow * Removed unused code * removed addFlow of useDuplicateFlows call * made newProject default as true * removed unused variables from addFlow * fixed url of requests of flows * passed functions directly * fix app to display loading on top of the router * fixed promise of addFlow * Added upload flow hook with a lot of modularity * Fixed addFlow naming * Added helper functions for file uploading * Changed upload flow to use helper functions * removed refresh on post * changed paste function to handle when chatinput node exists on paste * Used helper function to create input on FileInput * Used helper function to create input on InputFileComponent * Used helper function to create input on folder upload, and used uploadFlow hook * used uploadFlow hook on dropdown options * used addFlow instead of addComponent on node toolbar * changed upload flow on headerComponent to use hook * Changed pageComponent to use uploadFlow hook * removed useFileDrop dependency * Fixed onFileDrop to use uploadFlow * removed useDropdown dependency * removed unused add and upload functions from flowsManagerStore * Clean flows and refetch when flow change, added loader when is fetching * change name of delete flows api * created useDeleteFlow hook * used delete flow on useAddFlow * Used useDeleteFlow hook in places that used removeFlow and deleteComponent * deleted useDeleteMultiple hook * removed removeFlows and deleteComponent functions of flowsManagerStore * Deleted API flows delete call from API file --- .../src/components/headerComponent/index.tsx | 16 +++-- src/frontend/src/controllers/API/index.ts | 39 +----------- ...te-flows.ts => use-delete-delete-flows.ts} | 2 +- src/frontend/src/hooks/flows/use-add-flow.ts | 10 +-- .../src/hooks/flows/use-delete-flow.ts | 53 ++++++++++++++++ .../sideBarDraggableComponent/index.tsx | 9 +-- .../hooks/use-delete-multiple.tsx | 54 ---------------- .../components/componentsComponent/index.tsx | 49 +++++++-------- src/frontend/src/stores/flowsManagerStore.ts | 62 ------------------- .../src/types/zustand/flowsManager/index.ts | 2 - 10 files changed, 94 insertions(+), 202 deletions(-) rename src/frontend/src/controllers/API/queries/flows/{use-delete-flows.ts => use-delete-delete-flows.ts} (92%) create mode 100644 src/frontend/src/hooks/flows/use-delete-flow.ts delete mode 100644 src/frontend/src/pages/MainPage/components/componentsComponent/hooks/use-delete-multiple.tsx diff --git a/src/frontend/src/components/headerComponent/index.tsx b/src/frontend/src/components/headerComponent/index.tsx index 11ae845c6..c806b4d5c 100644 --- a/src/frontend/src/components/headerComponent/index.tsx +++ b/src/frontend/src/components/headerComponent/index.tsx @@ -3,7 +3,6 @@ import { FaDiscord, FaGithub } from "react-icons/fa"; import { RiTwitterXFill } from "react-icons/ri"; import { Link, useLocation, useNavigate, useParams } from "react-router-dom"; import AlertDropdown from "../../alerts/alertDropDown"; -import profileCircle from "../../assets/profile-circle.png"; import { BASE_URL_API, LOCATIONS_TO_RETURN, @@ -13,11 +12,11 @@ import { AuthContext } from "../../contexts/authContext"; import FeatureFlags from "@/../feature-config.json"; import { useLogout } from "@/controllers/API/queries/auth"; +import useDeleteFlow from "@/hooks/flows/use-delete-flow"; import useAuthStore from "@/stores/authStore"; import useAlertStore from "../../stores/alertStore"; import { useDarkStore } from "../../stores/darkStore"; import useFlowStore from "../../stores/flowStore"; -import useFlowsManagerStore from "../../stores/flowsManagerStore"; import { useLocationStore } from "../../stores/locationStore"; import { useStoreStore } from "../../stores/storeStore"; import IconComponent, { ForwardedIconComponent } from "../genericIconComponent"; @@ -45,7 +44,7 @@ export default function Header(): JSX.Element { const logout = useAuthStore((state) => state.logout); const navigate = useNavigate(); - const removeFlow = useFlowsManagerStore((store) => store.removeFlow); + const deleteFlow = useDeleteFlow(); const hasStore = useStoreStore((state) => state.hasStore); const { id } = useParams(); const nodes = useFlowStore((state) => state.nodes); @@ -56,13 +55,12 @@ export default function Header(): JSX.Element { const routeHistory = useLocationStore((state) => state.routeHistory); - const profileImageUrl = - `${BASE_URL_API}files/profile_pictures/${ - userData?.profile_image ?? "Space/046-rocket.svg" - }` ?? profileCircle; + const profileImageUrl = `${BASE_URL_API}files/profile_pictures/${ + userData?.profile_image ?? "Space/046-rocket.svg" + }`; async function checkForChanges(): Promise { - if (nodes.length === 0) { - await removeFlow(id!); + if (nodes.length === 0 && id) { + await deleteFlow({ id }); } } diff --git a/src/frontend/src/controllers/API/index.ts b/src/frontend/src/controllers/API/index.ts index 01213333c..e1918ccec 100644 --- a/src/frontend/src/controllers/API/index.ts +++ b/src/frontend/src/controllers/API/index.ts @@ -1,6 +1,6 @@ import { AxiosRequestConfig, AxiosResponse } from "axios"; import { Edge, Node, ReactFlowJsonObject } from "reactflow"; -import { BASE_URL_API, MAX_BATCH_SIZE } from "../../constants/constants"; +import { BASE_URL_API } from "../../constants/constants"; import { api } from "../../controllers/API/api"; import { APIObjectType, @@ -802,40 +802,3 @@ export async function deleteFlowPool( config["params"] = { flow_id: flowId }; return await api.delete(`${BASE_URL_API}monitor/builds`, config); } - -/** - * Deletes multiple flow components by their IDs. - * @param flowIds - An array of flow IDs to be deleted. - * @param token - The authorization token for the API request. - * @returns A promise that resolves to an array of AxiosResponse objects representing the delete responses. - */ -export async function multipleDeleteFlowsComponents( - flowIds: string[], -): Promise[]> { - const batches: string[][] = []; - - // Split the flowIds into batches - for (let i = 0; i < flowIds.length; i += MAX_BATCH_SIZE) { - batches.push(flowIds.slice(i, i + MAX_BATCH_SIZE)); - } - - // Function to delete a batch of flow IDs - const deleteBatch = async (batch: string[]): Promise> => { - try { - return await api.delete(`${BASE_URL_API}flows/`, { - data: batch, - }); - } catch (error) { - console.error("Error deleting flows:", error); - throw error; - } - }; - - // Execute all delete requests - const responses: Promise>[] = batches.map((batch) => - deleteBatch(batch), - ); - - // Return the responses after all requests are completed - return Promise.all(responses); -} diff --git a/src/frontend/src/controllers/API/queries/flows/use-delete-flows.ts b/src/frontend/src/controllers/API/queries/flows/use-delete-delete-flows.ts similarity index 92% rename from src/frontend/src/controllers/API/queries/flows/use-delete-flows.ts rename to src/frontend/src/controllers/API/queries/flows/use-delete-delete-flows.ts index 22ac82cb5..c059b6cd5 100644 --- a/src/frontend/src/controllers/API/queries/flows/use-delete-flows.ts +++ b/src/frontend/src/controllers/API/queries/flows/use-delete-delete-flows.ts @@ -8,7 +8,7 @@ interface IDeleteFlows { flow_ids: string[]; } -export const useDeleteFlows: useMutationFunctionType< +export const useDeleteDeleteFlows: useMutationFunctionType< undefined, IDeleteFlows > = (options?) => { diff --git a/src/frontend/src/hooks/flows/use-add-flow.ts b/src/frontend/src/hooks/flows/use-add-flow.ts index 451648f7b..d0aa221c4 100644 --- a/src/frontend/src/hooks/flows/use-add-flow.ts +++ b/src/frontend/src/hooks/flows/use-add-flow.ts @@ -14,6 +14,7 @@ import { updateGroupRecursion, } from "@/utils/reactflowUtils"; import { cloneDeep } from "lodash"; +import useDeleteFlow from "./use-delete-flow"; const useAddFlow = () => { const unavaliableFields = useGlobalVariablesStore( @@ -24,9 +25,7 @@ const useAddFlow = () => { ); const flows = useFlowsManagerStore((state) => state.flows); const setFlows = useFlowsManagerStore((state) => state.setFlows); - const deleteComponent = useFlowsManagerStore( - (state) => state.deleteComponent, - ); + const deleteFlow = useDeleteFlow(); const setIsLoading = useFlowsManagerStore((state) => state.setIsLoading); const { mutate: postAddFlow } = usePostAddFlow(); @@ -50,7 +49,10 @@ const useAddFlow = () => { const my_collection_id = useFolderStore.getState().myCollectionId; if (params?.override && flow) { - await deleteComponent(flow.name); + const flowId = flows.find((f) => f.name === flow.name); + if (flowId) { + await deleteFlow({ id: flowId.id }); + } } const newFlow = createNewFlow( flowData!, diff --git a/src/frontend/src/hooks/flows/use-delete-flow.ts b/src/frontend/src/hooks/flows/use-delete-flow.ts new file mode 100644 index 000000000..bc8c5d538 --- /dev/null +++ b/src/frontend/src/hooks/flows/use-delete-flow.ts @@ -0,0 +1,53 @@ +import { useDeleteDeleteFlows } from "@/controllers/API/queries/flows/use-delete-delete-flows"; +import useFlowsManagerStore from "@/stores/flowsManagerStore"; +import { useTypesStore } from "@/stores/typesStore"; +import { + extractFieldsFromComponenents, + processFlows, +} from "@/utils/reactflowUtils"; + +const useDeleteFlow = () => { + const flows = useFlowsManagerStore((state) => state.flows); + const setFlows = useFlowsManagerStore((state) => state.setFlows); + const setIsLoading = useFlowsManagerStore((state) => state.setIsLoading); + + const { mutate } = useDeleteDeleteFlows(); + + const deleteFlow = async ({ + id, + }: { + id: string | string[]; + }): Promise => { + return new Promise((resolve, reject) => { + if (!Array.isArray(id)) { + id = [id]; + } + mutate( + { flow_ids: id }, + { + onSuccess: () => { + const { data, flows: myFlows } = processFlows( + flows.filter((flow) => !id.includes(flow.id)), + ); + setFlows(myFlows); + setIsLoading(false); + useTypesStore.setState((state) => ({ + data: { ...state.data, ["saved_components"]: data }, + ComponentFields: extractFieldsFromComponenents({ + ...state.data, + ["saved_components"]: data, + }), + })); + + resolve(); + }, + onError: (e) => reject(e), + }, + ); + }); + }; + + return deleteFlow; +}; + +export default useDeleteFlow; diff --git a/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/sideBarDraggableComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/sideBarDraggableComponent/index.tsx index ed92defb9..835f98c69 100644 --- a/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/sideBarDraggableComponent/index.tsx +++ b/src/frontend/src/pages/FlowPage/components/extraSidebarComponent/sideBarDraggableComponent/index.tsx @@ -1,3 +1,4 @@ +import useDeleteFlow from "@/hooks/flows/use-delete-flow"; import { DragEventHandler, forwardRef, useRef, useState } from "react"; import IconComponent from "../../../../../components/genericIconComponent"; import { @@ -40,9 +41,8 @@ export const SidebarDraggableComponent = forwardRef( ref, ) => { const [open, setOpen] = useState(false); - const deleteComponent = useFlowsManagerStore( - (state) => state.deleteComponent, - ); + const deleteFlow = useDeleteFlow(); + const flows = useFlowsManagerStore((state) => state.flows); const version = useDarkStore((state) => state.version); const [cursorPos, setCursorPos] = useState({ x: 0, y: 0 }); @@ -72,7 +72,8 @@ export const SidebarDraggableComponent = forwardRef( ); break; case "delete": - deleteComponent(display_name); + const flowId = flows.find((f) => f.name === display_name); + if (flowId) deleteFlow({ id: flowId.id }); break; } } diff --git a/src/frontend/src/pages/MainPage/components/componentsComponent/hooks/use-delete-multiple.tsx b/src/frontend/src/pages/MainPage/components/componentsComponent/hooks/use-delete-multiple.tsx deleted file mode 100644 index e6b4bb11d..000000000 --- a/src/frontend/src/pages/MainPage/components/componentsComponent/hooks/use-delete-multiple.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import { FolderType } from "@/pages/MainPage/entities"; -import { FlowType } from "@/types/flow"; -import { useCallback } from "react"; - -const useDeleteMultipleFlows = ( - selectedFlowsComponentsCards: string[], - removeFlow: (selectedFlowsComponentsCards: string[]) => Promise, - resetFilter: () => void, - getFoldersApi: (refetch?: boolean) => Promise, - folderId: string | undefined, - myCollectionId: string, - getFolderById: (id: string) => void, - setSuccessData: (data: { title: string }) => void, - setErrorData: (data: { title: string; list: string[] }) => void, - setAllFlows: (flows: FlowType[]) => void, - setSelectedFolder: (folder: FolderType | null) => void, -) => { - const handleDeleteMultiple = useCallback(() => { - removeFlow(selectedFlowsComponentsCards) - .then(() => { - setAllFlows([]); - setSelectedFolder(null); - - resetFilter(); - getFoldersApi(true); - if (!folderId || folderId === myCollectionId) { - getFolderById(folderId ? folderId : myCollectionId); - } - setSuccessData({ - title: "Selected items deleted successfully", - }); - }) - .catch(() => { - setErrorData({ - title: "Error deleting items", - list: ["Please try again"], - }); - }); - }, [ - selectedFlowsComponentsCards, - removeFlow, - resetFilter, - getFoldersApi, - folderId, - myCollectionId, - getFolderById, - setSuccessData, - setErrorData, - ]); - - return { handleDeleteMultiple }; -}; - -export default useDeleteMultipleFlows; diff --git a/src/frontend/src/pages/MainPage/components/componentsComponent/index.tsx b/src/frontend/src/pages/MainPage/components/componentsComponent/index.tsx index b7884cf88..4719b60a1 100644 --- a/src/frontend/src/pages/MainPage/components/componentsComponent/index.tsx +++ b/src/frontend/src/pages/MainPage/components/componentsComponent/index.tsx @@ -1,5 +1,5 @@ import { usePostDownloadMultipleFlows } from "@/controllers/API/queries/flows"; -import { useDeleteFlows } from "@/controllers/API/queries/flows/use-delete-flows"; +import useDeleteFlow from "@/hooks/flows/use-delete-flow"; import { useEffect, useMemo, useState } from "react"; import { FormProvider, useForm, useWatch } from "react-hook-form"; import { useLocation } from "react-router-dom"; @@ -184,35 +184,28 @@ export default function ComponentsComponent({ handleExport, ); - const { mutate: mutateDeleteMultipleFlows } = useDeleteFlows(); + const deleteFlow = useDeleteFlow(); const handleDeleteMultiple = () => { - mutateDeleteMultipleFlows( - { - flow_ids: selectedFlowsComponentsCards, - }, - { - onSuccess: () => { - setAllFlows([]); - setSelectedFolder(null); - - resetFilter(); - getFoldersApi(true); - if (!folderId || folderId === myCollectionId) { - getFolderById(folderId ? folderId : myCollectionId); - } - setSuccessData({ - title: "Selected items deleted successfully", - }); - }, - onError: () => { - setErrorData({ - title: "Error deleting items", - list: ["Please try again"], - }); - }, - }, - ); + deleteFlow({ id: selectedFlowsComponentsCards }) + .then(() => { + setAllFlows([]); + setSelectedFolder(null); + resetFilter(); + getFoldersApi(true); + if (!folderId || folderId === myCollectionId) { + getFolderById(folderId ? folderId : myCollectionId); + } + setSuccessData({ + title: "Selected items deleted successfully", + }); + }) + .catch((e) => { + setErrorData({ + title: "Error deleting items", + list: ["Please try again"], + }); + }); }; useSelectedFlows(entireFormValues, setSelectedFlowsComponentsCards); diff --git a/src/frontend/src/stores/flowsManagerStore.ts b/src/frontend/src/stores/flowsManagerStore.ts index e47d815a2..1c2c69c37 100644 --- a/src/frontend/src/stores/flowsManagerStore.ts +++ b/src/frontend/src/stores/flowsManagerStore.ts @@ -5,8 +5,6 @@ import { Edge, Node, Viewport } from "reactflow"; import { create } from "zustand"; import { SAVE_DEBOUNCE_TIME } from "../constants/constants"; import { - deleteFlowFromDatabase, - multipleDeleteFlowsComponents, readFlowsFromDatabase, updateFlowInDatabase, } from "../controllers/API"; @@ -163,66 +161,6 @@ const useFlowsManagerStore = create((set, get) => ({ }); }); }, SAVE_DEBOUNCE_TIME), - removeFlow: async (id: string | string[]) => { - return new Promise((resolve, reject) => { - if (Array.isArray(id)) { - multipleDeleteFlowsComponents(id) - .then(() => { - const { data, flows } = processFlows( - get().flows.filter((flow) => !id.includes(flow.id)), - ); - get().setFlows(flows); - set({ isLoading: false }); - useTypesStore.setState((state) => ({ - data: { ...state.data, ["saved_components"]: data }, - ComponentFields: extractFieldsFromComponenents({ - ...state.data, - ["saved_components"]: data, - }), - })); - resolve(); - }) - .catch((e) => reject(e)); - } else { - const index = get().flows.findIndex((flow) => flow.id === id); - if (index >= 0) { - deleteFlowFromDatabase(id) - .then(() => { - const { data, flows } = processFlows( - get().flows.filter((flow) => flow.id !== id), - ); - get().setFlows(flows); - set({ isLoading: false }); - useTypesStore.setState((state) => ({ - data: { ...state.data, ["saved_components"]: data }, - ComponentFields: extractFieldsFromComponenents({ - ...state.data, - ["saved_components"]: data, - }), - })); - resolve(); - }) - .catch((e) => reject(e)); - } - } - }); - }, - deleteComponent: async (key: string) => { - return new Promise((resolve) => { - let componentFlow = get().flows.find( - (componentFlow) => - componentFlow.is_component && componentFlow.name === key, - ); - - if (componentFlow) { - get() - .removeFlow(componentFlow.id) - .then(() => { - resolve(); - }); - } - }); - }, takeSnapshot: () => { const currentFlowId = get().currentFlowId; // push the current graph to the past state diff --git a/src/frontend/src/types/zustand/flowsManager/index.ts b/src/frontend/src/types/zustand/flowsManager/index.ts index 70d7c01c4..c99c090bb 100644 --- a/src/frontend/src/types/zustand/flowsManager/index.ts +++ b/src/frontend/src/types/zustand/flowsManager/index.ts @@ -30,8 +30,6 @@ export type FlowsManagerStoreType = { edges: Edge[], viewport: Viewport, ) => void; - deleteComponent: (key: string) => Promise; - removeFlow: (id: string | string[]) => Promise; undo: () => void; redo: () => void; takeSnapshot: () => void;