fix: auto saving config (#3395)

* remove env definition from vite

* add get config query

* add save config hook to add info to autosaving and axios

* Use save config hook to get info

* Create autoSaving variable on flowsManagerStore

* Adds autoSaving from store into every place that used the env variables

* fix wrong url

---------

Co-authored-by: anovazzi1 <otavio2204@gmail.com>
This commit is contained in:
Lucas Oliveira 2024-08-16 17:23:11 -03:00 committed by GitHub
commit 0d60fbf3e7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 69 additions and 37 deletions

View file

@ -13,7 +13,7 @@ import {
useRefreshAccessToken,
} from "./controllers/API/queries/auth";
import { useGetVersionQuery } from "./controllers/API/queries/version";
import { setupAxiosDefaults } from "./controllers/API/utils";
import useSaveConfig from "./hooks/use-save-config";
import router from "./routes";
import useAlertStore from "./stores/alertStore";
import useAuthStore from "./stores/authStore";
@ -56,7 +56,7 @@ export default function App() {
login(user["access_token"], "auto");
setUserData(user);
setAutoLogin(true);
fetchAllData();
refreshStars();
// mutateRefresh({ refresh_token: refreshToken });
}
},
@ -70,7 +70,7 @@ export default function App() {
logout();
} else {
mutateRefresh({ refresh_token: refreshToken });
fetchAllData();
refreshStars();
getUser();
}
}
@ -96,25 +96,7 @@ export default function App() {
return () => clearInterval(intervalId);
}, [isLoginPage]);
const fetchAllData = async () => {
setTimeout(async () => {
await Promise.all([refreshStars(), fetchData()]);
}, 1000);
};
const fetchData = async () => {
return new Promise<void>(async (resolve, reject) => {
if (isAuthenticated) {
try {
await setupAxiosDefaults();
resolve();
} catch (error) {
console.error("Failed to fetch data:", error);
reject();
}
}
});
};
useSaveConfig();
return (
//need parent component with width and height

View file

@ -49,7 +49,7 @@ export const MenuBar = ({}: {}): JSX.Element => {
const isBuilding = useFlowStore((state) => state.isBuilding);
const getTypes = useTypesStore((state) => state.getTypes);
const saveFlow = useSaveFlow();
const shouldAutosave = process.env.LANGFLOW_AUTO_SAVING !== "false";
const autoSaving = useFlowsManagerStore((state) => state.autoSaving);
const currentFlow = useFlowStore((state) => state.currentFlow);
const currentSavedFlow = useFlowsManagerStore((state) => state.currentFlow);
const updatedAt = currentSavedFlow?.updated_at;
@ -58,7 +58,7 @@ export const MenuBar = ({}: {}): JSX.Element => {
const changesNotSaved =
customStringify(currentFlow) !== customStringify(currentSavedFlow) &&
!shouldAutosave;
!autoSaving;
const savedText =
updatedAt && changesNotSaved
@ -144,7 +144,7 @@ export const MenuBar = ({}: {}): JSX.Element => {
<IconComponent name="Settings2" className="header-menu-options" />
Settings
</DropdownMenuItem>
{!shouldAutosave && (
{!autoSaving && (
<DropdownMenuItem onClick={handleSave} className="cursor-pointer">
<ToolbarSelectItem
value="Save"
@ -252,11 +252,11 @@ export const MenuBar = ({}: {}): JSX.Element => {
<FlowLogsModal open={openLogs} setOpen={setOpenLogs}></FlowLogsModal>
</div>
<div className="flex items-center">
{!shouldAutosave && (
{!autoSaving && (
<Button
variant="primary"
size="icon"
disabled={shouldAutosave || !changesNotSaved || isBuilding}
disabled={autoSaving || !changesNotSaved || isBuilding}
className={cn("mr-1 h-9 px-2")}
onClick={handleSave}
>
@ -265,7 +265,7 @@ export const MenuBar = ({}: {}): JSX.Element => {
)}
<ShadTooltip
content={
shouldAutosave ? (
autoSaving ? (
SAVED_HOVER +
(updatedAt
? new Date(updatedAt).toLocaleString("en-US", {

View file

@ -18,6 +18,7 @@ export const URLs = {
FLOWS: `flows`,
FOLDERS: `folders`,
VARIABLES: `variables`,
CONFIG: `config`,
} as const;
export function getURL(key: keyof typeof URLs, params: any = {}) {

View file

@ -0,0 +1,25 @@
import { useQueryFunctionType } from "../../../../types/api";
import { api } from "../../api";
import { getURL } from "../../helpers/constants";
import { UseRequestProcessor } from "../../services/request-processor";
export interface ConfigResponse {
frontend_timeout: number;
auto_saving: boolean;
}
export const useGetConfigQuery: useQueryFunctionType<
undefined,
ConfigResponse
> = (options) => {
const { query } = UseRequestProcessor();
const getConfigFn = async () => {
const response = await api.get<ConfigResponse>(`${getURL("CONFIG")}`);
return response["data"];
};
const queryResult = query(["useGetConfigQuery"], getConfigFn, options);
return queryResult;
};

View file

@ -1,13 +1,14 @@
import { SAVE_DEBOUNCE_TIME } from "@/constants/constants";
import useFlowsManagerStore from "@/stores/flowsManagerStore";
import { FlowType } from "@/types/flow";
import { useDebounce } from "../use-debounce";
import useSaveFlow from "./use-save-flow";
const useAutoSaveFlow = () => {
const saveFlow = useSaveFlow();
const shouldAutosave = process.env.LANGFLOW_AUTO_SAVING !== "false";
const autoSaving = useFlowsManagerStore((state) => state.autoSaving);
const autoSaveFlow = shouldAutosave
const autoSaveFlow = autoSaving
? useDebounce((flow?: FlowType) => {
saveFlow(flow);
}, SAVE_DEBOUNCE_TIME)

View file

@ -0,0 +1,22 @@
import useFlowsManagerStore from "@/stores/flowsManagerStore";
import axios from "axios";
import { useEffect } from "react";
import { useGetConfigQuery } from "../controllers/API/queries/config/use-get-config";
function useSaveConfig() {
const { data } = useGetConfigQuery();
const setAutoSaving = useFlowsManagerStore((state) => state.setAutoSaving);
useEffect(() => {
if (data) {
const timeoutInMilliseconds = data.frontend_timeout
? data.frontend_timeout * 1000
: 30000;
axios.defaults.baseURL = "";
axios.defaults.timeout = timeoutInMilliseconds;
setAutoSaving(data.auto_saving);
}
}, [data]);
}
export default useSaveConfig;

View file

@ -33,7 +33,7 @@ export default function FlowSettingsModal({
);
const [isSaving, setIsSaving] = useState(false);
const [disableSave, setDisableSave] = useState(true);
const shouldAutosave = process.env.LANGFLOW_AUTO_SAVING !== "false";
const autoSaving = useFlowsManagerStore((state) => state.autoSaving);
function handleClick(): void {
setIsSaving(true);
if (!currentFlow) return;
@ -42,7 +42,7 @@ export default function FlowSettingsModal({
newFlow.description = description;
newFlow.endpoint_name =
endpoint_name && endpoint_name.length > 0 ? endpoint_name : null;
if (shouldAutosave) {
if (autoSaving) {
saveFlow(newFlow)
?.then(() => {
setOpen(false);

View file

@ -39,7 +39,7 @@ export default function FlowPage({ view }: { view?: boolean }): JSX.Element {
const updatedAt = currentSavedFlow?.updated_at;
const shouldAutosave = process.env.LANGFLOW_AUTO_SAVING !== "false";
const autoSaving = useFlowsManagerStore((state) => state.autoSaving);
const handleSave = () => {
saveFlow().then(() => (blocker.proceed ? blocker.proceed() : null));
@ -136,7 +136,7 @@ export default function FlowPage({ view }: { view?: boolean }): JSX.Element {
})
: undefined
}
autoSave={shouldAutosave}
autoSave={autoSaving}
/>
)}
</>

View file

@ -24,6 +24,8 @@ const past = {};
const future = {};
const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
autoSaving: true,
setAutoSaving: (autoSaving: boolean) => set({ autoSaving }),
examples: [],
setExamples: (examples: FlowType[]) => {
set({ examples });

View file

@ -1,6 +1,8 @@
import { FlowType } from "../../flow";
export type FlowsManagerStoreType = {
autoSaving: boolean;
setAutoSaving: (autoSaving: boolean) => void;
getFlowById: (id: string) => FlowType | undefined;
flows: Array<FlowType> | undefined;
setFlows: (flows: FlowType[]) => void;

View file

@ -31,9 +31,6 @@ export default defineConfig(({ mode }) => {
outDir: "build",
},
define: {
"process.env.LANGFLOW_AUTO_SAVING": JSON.stringify(
process.env.LANGFLOW_AUTO_SAVING,
),
"process.env.BACKEND_URL": JSON.stringify(process.env.BACKEND_URL),
"process.env.ACCESS_TOKEN_EXPIRE_SECONDS": JSON.stringify(
process.env.ACCESS_TOKEN_EXPIRE_SECONDS,