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:
parent
b0619f59ff
commit
0d60fbf3e7
11 changed files with 69 additions and 37 deletions
|
|
@ -13,7 +13,7 @@ import {
|
||||||
useRefreshAccessToken,
|
useRefreshAccessToken,
|
||||||
} from "./controllers/API/queries/auth";
|
} from "./controllers/API/queries/auth";
|
||||||
import { useGetVersionQuery } from "./controllers/API/queries/version";
|
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 router from "./routes";
|
||||||
import useAlertStore from "./stores/alertStore";
|
import useAlertStore from "./stores/alertStore";
|
||||||
import useAuthStore from "./stores/authStore";
|
import useAuthStore from "./stores/authStore";
|
||||||
|
|
@ -56,7 +56,7 @@ export default function App() {
|
||||||
login(user["access_token"], "auto");
|
login(user["access_token"], "auto");
|
||||||
setUserData(user);
|
setUserData(user);
|
||||||
setAutoLogin(true);
|
setAutoLogin(true);
|
||||||
fetchAllData();
|
refreshStars();
|
||||||
// mutateRefresh({ refresh_token: refreshToken });
|
// mutateRefresh({ refresh_token: refreshToken });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -70,7 +70,7 @@ export default function App() {
|
||||||
logout();
|
logout();
|
||||||
} else {
|
} else {
|
||||||
mutateRefresh({ refresh_token: refreshToken });
|
mutateRefresh({ refresh_token: refreshToken });
|
||||||
fetchAllData();
|
refreshStars();
|
||||||
getUser();
|
getUser();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -96,25 +96,7 @@ export default function App() {
|
||||||
return () => clearInterval(intervalId);
|
return () => clearInterval(intervalId);
|
||||||
}, [isLoginPage]);
|
}, [isLoginPage]);
|
||||||
|
|
||||||
const fetchAllData = async () => {
|
useSaveConfig();
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
//need parent component with width and height
|
//need parent component with width and height
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ export const MenuBar = ({}: {}): JSX.Element => {
|
||||||
const isBuilding = useFlowStore((state) => state.isBuilding);
|
const isBuilding = useFlowStore((state) => state.isBuilding);
|
||||||
const getTypes = useTypesStore((state) => state.getTypes);
|
const getTypes = useTypesStore((state) => state.getTypes);
|
||||||
const saveFlow = useSaveFlow();
|
const saveFlow = useSaveFlow();
|
||||||
const shouldAutosave = process.env.LANGFLOW_AUTO_SAVING !== "false";
|
const autoSaving = useFlowsManagerStore((state) => state.autoSaving);
|
||||||
const currentFlow = useFlowStore((state) => state.currentFlow);
|
const currentFlow = useFlowStore((state) => state.currentFlow);
|
||||||
const currentSavedFlow = useFlowsManagerStore((state) => state.currentFlow);
|
const currentSavedFlow = useFlowsManagerStore((state) => state.currentFlow);
|
||||||
const updatedAt = currentSavedFlow?.updated_at;
|
const updatedAt = currentSavedFlow?.updated_at;
|
||||||
|
|
@ -58,7 +58,7 @@ export const MenuBar = ({}: {}): JSX.Element => {
|
||||||
|
|
||||||
const changesNotSaved =
|
const changesNotSaved =
|
||||||
customStringify(currentFlow) !== customStringify(currentSavedFlow) &&
|
customStringify(currentFlow) !== customStringify(currentSavedFlow) &&
|
||||||
!shouldAutosave;
|
!autoSaving;
|
||||||
|
|
||||||
const savedText =
|
const savedText =
|
||||||
updatedAt && changesNotSaved
|
updatedAt && changesNotSaved
|
||||||
|
|
@ -144,7 +144,7 @@ export const MenuBar = ({}: {}): JSX.Element => {
|
||||||
<IconComponent name="Settings2" className="header-menu-options" />
|
<IconComponent name="Settings2" className="header-menu-options" />
|
||||||
Settings
|
Settings
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
{!shouldAutosave && (
|
{!autoSaving && (
|
||||||
<DropdownMenuItem onClick={handleSave} className="cursor-pointer">
|
<DropdownMenuItem onClick={handleSave} className="cursor-pointer">
|
||||||
<ToolbarSelectItem
|
<ToolbarSelectItem
|
||||||
value="Save"
|
value="Save"
|
||||||
|
|
@ -252,11 +252,11 @@ export const MenuBar = ({}: {}): JSX.Element => {
|
||||||
<FlowLogsModal open={openLogs} setOpen={setOpenLogs}></FlowLogsModal>
|
<FlowLogsModal open={openLogs} setOpen={setOpenLogs}></FlowLogsModal>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
{!shouldAutosave && (
|
{!autoSaving && (
|
||||||
<Button
|
<Button
|
||||||
variant="primary"
|
variant="primary"
|
||||||
size="icon"
|
size="icon"
|
||||||
disabled={shouldAutosave || !changesNotSaved || isBuilding}
|
disabled={autoSaving || !changesNotSaved || isBuilding}
|
||||||
className={cn("mr-1 h-9 px-2")}
|
className={cn("mr-1 h-9 px-2")}
|
||||||
onClick={handleSave}
|
onClick={handleSave}
|
||||||
>
|
>
|
||||||
|
|
@ -265,7 +265,7 @@ export const MenuBar = ({}: {}): JSX.Element => {
|
||||||
)}
|
)}
|
||||||
<ShadTooltip
|
<ShadTooltip
|
||||||
content={
|
content={
|
||||||
shouldAutosave ? (
|
autoSaving ? (
|
||||||
SAVED_HOVER +
|
SAVED_HOVER +
|
||||||
(updatedAt
|
(updatedAt
|
||||||
? new Date(updatedAt).toLocaleString("en-US", {
|
? new Date(updatedAt).toLocaleString("en-US", {
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ export const URLs = {
|
||||||
FLOWS: `flows`,
|
FLOWS: `flows`,
|
||||||
FOLDERS: `folders`,
|
FOLDERS: `folders`,
|
||||||
VARIABLES: `variables`,
|
VARIABLES: `variables`,
|
||||||
|
CONFIG: `config`,
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export function getURL(key: keyof typeof URLs, params: any = {}) {
|
export function getURL(key: keyof typeof URLs, params: any = {}) {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
};
|
||||||
|
|
@ -1,13 +1,14 @@
|
||||||
import { SAVE_DEBOUNCE_TIME } from "@/constants/constants";
|
import { SAVE_DEBOUNCE_TIME } from "@/constants/constants";
|
||||||
|
import useFlowsManagerStore from "@/stores/flowsManagerStore";
|
||||||
import { FlowType } from "@/types/flow";
|
import { FlowType } from "@/types/flow";
|
||||||
import { useDebounce } from "../use-debounce";
|
import { useDebounce } from "../use-debounce";
|
||||||
import useSaveFlow from "./use-save-flow";
|
import useSaveFlow from "./use-save-flow";
|
||||||
|
|
||||||
const useAutoSaveFlow = () => {
|
const useAutoSaveFlow = () => {
|
||||||
const saveFlow = useSaveFlow();
|
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) => {
|
? useDebounce((flow?: FlowType) => {
|
||||||
saveFlow(flow);
|
saveFlow(flow);
|
||||||
}, SAVE_DEBOUNCE_TIME)
|
}, SAVE_DEBOUNCE_TIME)
|
||||||
|
|
|
||||||
22
src/frontend/src/hooks/use-save-config.ts
Normal file
22
src/frontend/src/hooks/use-save-config.ts
Normal 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;
|
||||||
|
|
@ -33,7 +33,7 @@ export default function FlowSettingsModal({
|
||||||
);
|
);
|
||||||
const [isSaving, setIsSaving] = useState(false);
|
const [isSaving, setIsSaving] = useState(false);
|
||||||
const [disableSave, setDisableSave] = useState(true);
|
const [disableSave, setDisableSave] = useState(true);
|
||||||
const shouldAutosave = process.env.LANGFLOW_AUTO_SAVING !== "false";
|
const autoSaving = useFlowsManagerStore((state) => state.autoSaving);
|
||||||
function handleClick(): void {
|
function handleClick(): void {
|
||||||
setIsSaving(true);
|
setIsSaving(true);
|
||||||
if (!currentFlow) return;
|
if (!currentFlow) return;
|
||||||
|
|
@ -42,7 +42,7 @@ export default function FlowSettingsModal({
|
||||||
newFlow.description = description;
|
newFlow.description = description;
|
||||||
newFlow.endpoint_name =
|
newFlow.endpoint_name =
|
||||||
endpoint_name && endpoint_name.length > 0 ? endpoint_name : null;
|
endpoint_name && endpoint_name.length > 0 ? endpoint_name : null;
|
||||||
if (shouldAutosave) {
|
if (autoSaving) {
|
||||||
saveFlow(newFlow)
|
saveFlow(newFlow)
|
||||||
?.then(() => {
|
?.then(() => {
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ export default function FlowPage({ view }: { view?: boolean }): JSX.Element {
|
||||||
|
|
||||||
const updatedAt = currentSavedFlow?.updated_at;
|
const updatedAt = currentSavedFlow?.updated_at;
|
||||||
|
|
||||||
const shouldAutosave = process.env.LANGFLOW_AUTO_SAVING !== "false";
|
const autoSaving = useFlowsManagerStore((state) => state.autoSaving);
|
||||||
|
|
||||||
const handleSave = () => {
|
const handleSave = () => {
|
||||||
saveFlow().then(() => (blocker.proceed ? blocker.proceed() : null));
|
saveFlow().then(() => (blocker.proceed ? blocker.proceed() : null));
|
||||||
|
|
@ -136,7 +136,7 @@ export default function FlowPage({ view }: { view?: boolean }): JSX.Element {
|
||||||
})
|
})
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
autoSave={shouldAutosave}
|
autoSave={autoSaving}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@ const past = {};
|
||||||
const future = {};
|
const future = {};
|
||||||
|
|
||||||
const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
|
const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
|
||||||
|
autoSaving: true,
|
||||||
|
setAutoSaving: (autoSaving: boolean) => set({ autoSaving }),
|
||||||
examples: [],
|
examples: [],
|
||||||
setExamples: (examples: FlowType[]) => {
|
setExamples: (examples: FlowType[]) => {
|
||||||
set({ examples });
|
set({ examples });
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
import { FlowType } from "../../flow";
|
import { FlowType } from "../../flow";
|
||||||
|
|
||||||
export type FlowsManagerStoreType = {
|
export type FlowsManagerStoreType = {
|
||||||
|
autoSaving: boolean;
|
||||||
|
setAutoSaving: (autoSaving: boolean) => void;
|
||||||
getFlowById: (id: string) => FlowType | undefined;
|
getFlowById: (id: string) => FlowType | undefined;
|
||||||
flows: Array<FlowType> | undefined;
|
flows: Array<FlowType> | undefined;
|
||||||
setFlows: (flows: FlowType[]) => void;
|
setFlows: (flows: FlowType[]) => void;
|
||||||
|
|
|
||||||
|
|
@ -31,9 +31,6 @@ export default defineConfig(({ mode }) => {
|
||||||
outDir: "build",
|
outDir: "build",
|
||||||
},
|
},
|
||||||
define: {
|
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.BACKEND_URL": JSON.stringify(process.env.BACKEND_URL),
|
||||||
"process.env.ACCESS_TOKEN_EXPIRE_SECONDS": JSON.stringify(
|
"process.env.ACCESS_TOKEN_EXPIRE_SECONDS": JSON.stringify(
|
||||||
process.env.ACCESS_TOKEN_EXPIRE_SECONDS,
|
process.env.ACCESS_TOKEN_EXPIRE_SECONDS,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue