refactor: add useGetRefreshFlows mutation and update code to use it (#3475)
* Added refresh flows mutation * Changed places that used refreshFlows to use the mutation * removed old refreshFlows * removed readFlowsFromDatabase api call * Removed unused API calls from API.ts * Removed getFlowFromDatabase call
This commit is contained in:
parent
0586d1e1d5
commit
3a408c8141
8 changed files with 79 additions and 207 deletions
|
|
@ -55,157 +55,6 @@ export async function sendAll(data: sendAllProps) {
|
|||
return await api.post(`${BASE_URL_API}predict`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a list of JSON files from a GitHub repository and returns their contents as an array of FlowType objects.
|
||||
*
|
||||
* @returns {Promise<FlowType[]>} A promise that resolves to an array of FlowType objects.
|
||||
*/
|
||||
export async function getExamples(): Promise<FlowType[]> {
|
||||
const url =
|
||||
"https://api.github.com/repos/langflow-ai/langflow_examples/contents/examples?ref=main";
|
||||
const response = await api.get(url);
|
||||
|
||||
const jsonFiles = response?.data.filter((file: any) => {
|
||||
return file.name.endsWith(".json");
|
||||
});
|
||||
|
||||
const contentsPromises = jsonFiles.map(async (file: any) => {
|
||||
const contentResponse = await api.get(file.download_url);
|
||||
return contentResponse.data;
|
||||
});
|
||||
|
||||
return await Promise.all(contentsPromises);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves a new flow to the database.
|
||||
*
|
||||
* @param {FlowType} newFlow - The flow data to save.
|
||||
* @returns {Promise<any>} The saved flow data.
|
||||
* @throws Will throw an error if saving fails.
|
||||
*/
|
||||
export async function saveFlowToDatabase(newFlow: {
|
||||
name: string;
|
||||
id: string;
|
||||
data: ReactFlowJsonObject | null;
|
||||
description: string;
|
||||
style?: FlowStyleType;
|
||||
is_component?: boolean;
|
||||
folder_id?: string;
|
||||
endpoint_name?: string;
|
||||
}): Promise<FlowType> {
|
||||
try {
|
||||
const response = await api.post(`${BASE_URL_API}flows/`, {
|
||||
name: newFlow.name,
|
||||
data: newFlow.data,
|
||||
description: newFlow.description,
|
||||
is_component: newFlow.is_component,
|
||||
folder_id: newFlow.folder_id === "" ? null : newFlow.folder_id,
|
||||
endpoint_name: newFlow.endpoint_name,
|
||||
});
|
||||
|
||||
if (response?.status !== 201) {
|
||||
throw new Error(`HTTP error! status: ${response?.status}`);
|
||||
}
|
||||
return response?.data;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads all flows from the database.
|
||||
*
|
||||
* @returns {Promise<any>} The flows data.
|
||||
* @throws Will throw an error if reading fails.
|
||||
*/
|
||||
export async function readFlowsFromDatabase() {
|
||||
try {
|
||||
const response = await api.get(`${BASE_URL_API}flows/`);
|
||||
if (response && response?.status !== 200) {
|
||||
throw new Error(`HTTP error! status: ${response?.status}`);
|
||||
}
|
||||
return response?.data;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export async function uploadFlowsToDatabase(flows: FormData) {
|
||||
try {
|
||||
const response = await api.post(`${BASE_URL_API}flows/upload/`, flows);
|
||||
|
||||
if (response?.status !== 201) {
|
||||
throw new Error(`HTTP error! status: ${response?.status}`);
|
||||
}
|
||||
return response?.data;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a flow from the database.
|
||||
*
|
||||
* @param {string} flowId - The ID of the flow to delete.
|
||||
* @returns {Promise<any>} The deleted flow data.
|
||||
* @throws Will throw an error if deletion fails.
|
||||
*/
|
||||
export async function deleteFlowFromDatabase(flowId: string) {
|
||||
try {
|
||||
const response = await api.delete(`${BASE_URL_API}flows/${flowId}`);
|
||||
if (response.status !== 200) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
return response?.data;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a flow from the database by ID.
|
||||
*
|
||||
* @param {number} flowId - The ID of the flow to fetch.
|
||||
* @returns {Promise<any>} The flow data.
|
||||
* @throws Will throw an error if fetching fails.
|
||||
*/
|
||||
export async function getFlowFromDatabase(flowId: number) {
|
||||
try {
|
||||
const response = await api.get(`${BASE_URL_API}flows/${flowId}`);
|
||||
if (response && response?.status !== 200) {
|
||||
throw new Error(`HTTP error! status: ${response?.status}`);
|
||||
}
|
||||
return response?.data;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches flow styles from the database.
|
||||
*
|
||||
* @returns {Promise<any>} The flow styles data.
|
||||
* @throws Will throw an error if fetching fails.
|
||||
*/
|
||||
export async function getFlowStylesFromDatabase() {
|
||||
try {
|
||||
const response = await api.get(`${BASE_URL_API}flow_styles/`);
|
||||
if (response.status !== 200) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
return response?.data;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the version of the API.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
import useAlertStore from "@/stores/alertStore";
|
||||
import useFlowsManagerStore from "@/stores/flowsManagerStore";
|
||||
import { useFolderStore } from "@/stores/foldersStore";
|
||||
import { useTypesStore } from "@/stores/typesStore";
|
||||
import { useMutationFunctionType } from "@/types/api";
|
||||
import { FlowType } from "@/types/flow";
|
||||
import {
|
||||
extractFieldsFromComponenents,
|
||||
processFlows,
|
||||
} from "@/utils/reactflowUtils";
|
||||
import { UseMutationResult } from "@tanstack/react-query";
|
||||
import { api } from "../../api";
|
||||
import { getURL } from "../../helpers/constants";
|
||||
import { UseRequestProcessor } from "../../services/request-processor";
|
||||
|
||||
export const useGetRefreshFlows: useMutationFunctionType<
|
||||
undefined,
|
||||
undefined
|
||||
> = (options?) => {
|
||||
const { mutate } = UseRequestProcessor();
|
||||
|
||||
const setExamples = useFlowsManagerStore((state) => state.setExamples);
|
||||
const setFlows = useFlowsManagerStore((state) => state.setFlows);
|
||||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||
const starterProjectId = useFolderStore((state) => state.starterProjectId);
|
||||
|
||||
const getRefreshFlowsFn = async (): Promise<void> => {
|
||||
try {
|
||||
} catch (e) {
|
||||
setErrorData({
|
||||
title: "Could not load flows from database",
|
||||
});
|
||||
throw e;
|
||||
}
|
||||
const response = await api.get<FlowType[]>(`${getURL("FLOWS")}/`);
|
||||
const dbData = response.data;
|
||||
if (dbData) {
|
||||
const { data, flows } = processFlows(dbData);
|
||||
const examples = flows.filter(
|
||||
(flow) => flow.folder_id === starterProjectId,
|
||||
);
|
||||
setExamples(examples);
|
||||
|
||||
const flowsWithoutStarterFolder = flows.filter(
|
||||
(flow) => flow.folder_id !== starterProjectId,
|
||||
);
|
||||
|
||||
setFlows(flowsWithoutStarterFolder);
|
||||
useTypesStore.setState((state) => ({
|
||||
data: { ...state.data, ["saved_components"]: data },
|
||||
ComponentFields: extractFieldsFromComponenents({
|
||||
...state.data,
|
||||
["saved_components"]: data,
|
||||
}),
|
||||
}));
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
const mutation: UseMutationResult<void, any, undefined> = mutate(
|
||||
["useGetRefreshFlows"],
|
||||
getRefreshFlowsFn,
|
||||
options,
|
||||
);
|
||||
|
||||
return mutation;
|
||||
};
|
||||
|
|
@ -1,18 +1,19 @@
|
|||
import { DEFAULT_FOLDER, STARTER_FOLDER_NAME } from "@/constants/constants";
|
||||
import { FolderType } from "@/pages/MainPage/entities";
|
||||
import useFlowsManagerStore from "@/stores/flowsManagerStore";
|
||||
import { useFolderStore } from "@/stores/foldersStore";
|
||||
import { useTypesStore } from "@/stores/typesStore";
|
||||
import { useQueryFunctionType } from "@/types/api";
|
||||
import { api } from "../../api";
|
||||
import { getURL } from "../../helpers/constants";
|
||||
import { UseRequestProcessor } from "../../services/request-processor";
|
||||
import { useGetRefreshFlows } from "../flows/use-get-refresh-flows";
|
||||
|
||||
export const useGetFoldersQuery: useQueryFunctionType<
|
||||
undefined,
|
||||
FolderType[]
|
||||
> = (options) => {
|
||||
const { query } = UseRequestProcessor();
|
||||
const { mutateAsync: refreshFlows } = useGetRefreshFlows();
|
||||
|
||||
const setStarterProjectId = useFolderStore(
|
||||
(state) => state.setStarterProjectId,
|
||||
|
|
@ -36,10 +37,9 @@ export const useGetFoldersQuery: useQueryFunctionType<
|
|||
const myCollectionId = data?.find((f) => f.name === DEFAULT_FOLDER)?.id;
|
||||
setMyCollectionId(myCollectionId);
|
||||
|
||||
const { refreshFlows } = useFlowsManagerStore.getState();
|
||||
const { getTypes } = useTypesStore.getState();
|
||||
|
||||
await refreshFlows();
|
||||
await refreshFlows(undefined);
|
||||
await getTypes();
|
||||
|
||||
return foldersWithoutStarterProjects;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useGetRefreshFlows } from "@/controllers/API/queries/flows/use-get-refresh-flows";
|
||||
import { createFileUpload } from "@/helpers/create-file-upload";
|
||||
import { getObjectsFromFilelist } from "@/helpers/get-objects-from-filelist";
|
||||
import useFlowStore from "@/stores/flowStore";
|
||||
import useFlowsManagerStore from "@/stores/flowsManagerStore";
|
||||
import { FlowType } from "@/types/flow";
|
||||
import { processDataFromFlow } from "@/utils/reactflowUtils";
|
||||
import useAddFlow from "./use-add-flow";
|
||||
|
|
@ -9,7 +9,7 @@ import useAddFlow from "./use-add-flow";
|
|||
const useUploadFlow = () => {
|
||||
const addFlow = useAddFlow();
|
||||
const paste = useFlowStore((state) => state.paste);
|
||||
const refreshFlows = useFlowsManagerStore((state) => state.refreshFlows);
|
||||
const { mutate: refreshFlows } = useGetRefreshFlows();
|
||||
|
||||
const getFlowsFromFiles = async ({
|
||||
files,
|
||||
|
|
@ -90,7 +90,7 @@ const useUploadFlow = () => {
|
|||
throw new Error("Invalid flow data");
|
||||
}
|
||||
}
|
||||
refreshFlows();
|
||||
refreshFlows(undefined);
|
||||
}
|
||||
} catch (e) {
|
||||
throw e;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import FeatureFlags from "@/../feature-config.json";
|
||||
import { useGetRefreshFlows } from "@/controllers/API/queries/flows/use-get-refresh-flows";
|
||||
import { useGetGlobalVariables } from "@/controllers/API/queries/variables";
|
||||
import useSaveFlow from "@/hooks/flows/use-save-flow";
|
||||
import { SaveChangesModal } from "@/modals/saveChangesModal";
|
||||
|
|
@ -33,7 +34,7 @@ export default function FlowPage({ view }: { view?: boolean }): JSX.Element {
|
|||
|
||||
const flows = useFlowsManagerStore((state) => state.flows);
|
||||
const currentFlowId = useFlowsManagerStore((state) => state.currentFlowId);
|
||||
const refreshFlows = useFlowsManagerStore((state) => state.refreshFlows);
|
||||
const { mutateAsync: refreshFlows } = useGetRefreshFlows();
|
||||
const setIsLoading = useFlowsManagerStore((state) => state.setIsLoading);
|
||||
const getTypes = useTypesStore((state) => state.getTypes);
|
||||
|
||||
|
|
@ -74,7 +75,7 @@ export default function FlowPage({ view }: { view?: boolean }): JSX.Element {
|
|||
setCurrentFlow(isAnExistingFlow);
|
||||
} else if (!flows) {
|
||||
setIsLoading(true);
|
||||
await refreshFlows();
|
||||
await refreshFlows(undefined);
|
||||
await getTypes();
|
||||
setIsLoading(false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { useGetRefreshFlows } from "@/controllers/API/queries/flows/use-get-refresh-flows";
|
||||
import { useGetGlobalVariables } from "@/controllers/API/queries/variables";
|
||||
import useFlowStore from "@/stores/flowStore";
|
||||
import { useTypesStore } from "@/stores/typesStore";
|
||||
|
|
@ -16,7 +17,7 @@ export default function ViewPage() {
|
|||
|
||||
const flows = useFlowsManagerStore((state) => state.flows);
|
||||
const currentFlowId = useFlowsManagerStore((state) => state.currentFlowId);
|
||||
const refreshFlows = useFlowsManagerStore((state) => state.refreshFlows);
|
||||
const { mutateAsync: refreshFlows } = useGetRefreshFlows();
|
||||
const setIsLoading = useFlowsManagerStore((state) => state.setIsLoading);
|
||||
const getTypes = useTypesStore((state) => state.getTypes);
|
||||
|
||||
|
|
@ -34,7 +35,7 @@ export default function ViewPage() {
|
|||
setCurrentFlow(isAnExistingFlow);
|
||||
} else if (!flows) {
|
||||
setIsLoading(true);
|
||||
await refreshFlows();
|
||||
await refreshFlows(undefined);
|
||||
await getTypes();
|
||||
setIsLoading(false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,11 @@
|
|||
import { cloneDeep } from "lodash";
|
||||
import { create } from "zustand";
|
||||
import { readFlowsFromDatabase } from "../controllers/API";
|
||||
import { FlowType } from "../types/flow";
|
||||
import {
|
||||
FlowsManagerStoreType,
|
||||
UseUndoRedoOptions,
|
||||
} from "../types/zustand/flowsManager";
|
||||
import {
|
||||
extractFieldsFromComponenents,
|
||||
processFlows,
|
||||
} from "../utils/reactflowUtils";
|
||||
import useAlertStore from "./alertStore";
|
||||
import useFlowStore from "./flowStore";
|
||||
import { useFolderStore } from "./foldersStore";
|
||||
import { useTypesStore } from "./typesStore";
|
||||
|
||||
const defaultOptions: UseUndoRedoOptions = {
|
||||
maxHistorySize: 100,
|
||||
|
|
@ -53,43 +45,6 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
|
|||
setSaveLoading: (saveLoading: boolean) => set({ saveLoading }),
|
||||
isLoading: false,
|
||||
setIsLoading: (isLoading: boolean) => set({ isLoading }),
|
||||
refreshFlows: () => {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
const starterFolderId = useFolderStore.getState().starterProjectId;
|
||||
|
||||
readFlowsFromDatabase()
|
||||
.then((dbData) => {
|
||||
if (dbData) {
|
||||
const { data, flows } = processFlows(dbData);
|
||||
const examples = flows.filter(
|
||||
(flow) => flow.folder_id === starterFolderId,
|
||||
);
|
||||
get().setExamples(examples);
|
||||
|
||||
const flowsWithoutStarterFolder = flows.filter(
|
||||
(flow) => flow.folder_id !== starterFolderId,
|
||||
);
|
||||
|
||||
get().setFlows(flowsWithoutStarterFolder);
|
||||
useTypesStore.setState((state) => ({
|
||||
data: { ...state.data, ["saved_components"]: data },
|
||||
ComponentFields: extractFieldsFromComponenents({
|
||||
...state.data,
|
||||
["saved_components"]: data,
|
||||
}),
|
||||
}));
|
||||
resolve();
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
set({ isLoading: false });
|
||||
useAlertStore.getState().setErrorData({
|
||||
title: "Could not load flows from database",
|
||||
});
|
||||
reject(e);
|
||||
});
|
||||
});
|
||||
},
|
||||
takeSnapshot: () => {
|
||||
const currentFlowId = get().currentFlowId;
|
||||
// push the current graph to the past state
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ export type FlowsManagerStoreType = {
|
|||
setSaveLoading: (saveLoading: boolean) => void;
|
||||
isLoading: boolean;
|
||||
setIsLoading: (isLoading: boolean) => void;
|
||||
refreshFlows: () => Promise<void>;
|
||||
undo: () => void;
|
||||
redo: () => void;
|
||||
takeSnapshot: () => void;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue