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:
parent
4d66bf351d
commit
f0bbf127c5
10 changed files with 94 additions and 202 deletions
|
|
@ -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 });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ interface IDeleteFlows {
|
|||
flow_ids: string[];
|
||||
}
|
||||
|
||||
export const useDeleteFlows: useMutationFunctionType<
|
||||
export const useDeleteDeleteFlows: useMutationFunctionType<
|
||||
undefined,
|
||||
IDeleteFlows
|
||||
> = (options?) => {
|
||||
|
|
@ -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!,
|
||||
|
|
|
|||
53
src/frontend/src/hooks/flows/use-delete-flow.ts
Normal file
53
src/frontend/src/hooks/flows/use-delete-flow.ts
Normal 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;
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue