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
This commit is contained in:
Lucas Oliveira 2024-08-07 09:55:19 -03:00 committed by GitHub
commit f0bbf127c5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 94 additions and 202 deletions

View file

@ -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<void> {
if (nodes.length === 0) {
await removeFlow(id!);
if (nodes.length === 0 && id) {
await deleteFlow({ id });
}
}

View file

@ -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<AxiosResponse<any>[]> {
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<AxiosResponse<any>> => {
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<AxiosResponse<any>>[] = batches.map((batch) =>
deleteBatch(batch),
);
// Return the responses after all requests are completed
return Promise.all(responses);
}

View file

@ -8,7 +8,7 @@ interface IDeleteFlows {
flow_ids: string[];
}
export const useDeleteFlows: useMutationFunctionType<
export const useDeleteDeleteFlows: useMutationFunctionType<
undefined,
IDeleteFlows
> = (options?) => {

View file

@ -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!,

View file

@ -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<void> => {
return new Promise<void>((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;

View file

@ -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;
}
}

View file

@ -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<void>,
resetFilter: () => void,
getFoldersApi: (refetch?: boolean) => Promise<void>,
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;

View file

@ -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);

View file

@ -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<FlowsManagerStoreType>((set, get) => ({
});
});
}, SAVE_DEBOUNCE_TIME),
removeFlow: async (id: string | string[]) => {
return new Promise<void>((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<void>((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

View file

@ -30,8 +30,6 @@ export type FlowsManagerStoreType = {
edges: Edge[],
viewport: Viewport,
) => void;
deleteComponent: (key: string) => Promise<void>;
removeFlow: (id: string | string[]) => Promise<void>;
undo: () => void;
redo: () => void;
takeSnapshot: () => void;