Skip to content

Commit

Permalink
refactor: folder fetching, folder sidebar and fix various issues (#3344)
Browse files Browse the repository at this point in the history
* Removed unused code

* Separated folder sidebar from common sidebar

* Removed useOnFileDrop from common sidebar

* Added folderSidebarComponent that fetches the folders

* Added useOnFileDrop and SIdebarFoldersButton

* Make auth context not get folders

* Make delete folder refetch get folders

* Make folder mutations refetch the getFolder

* Create getFolder query

* Removed unused functions from useFolderStore

* Make isLoading from application depend only on flows

* Make main page not refetch folders

* Change types of folders store

* removed getFolders refetch on duplicateFolders

* Added loading from query into ComponentsComponent

* Made the flow page get the flows and types if they're not available

* Made the loading be the isLoading only

* Removed unused function

* Make cards appear even if it didnt load

* Removed setLoading of various pages

* Fixed loading happening every time the flow changes

* Added skeleton instead of loading on folders

* Added routing to contain folderId on both flows and initial page

* remove redirect of useFileDrop

* remove folderid getting from state

* removed setAllFlows

* chore: Remove unused variables and functions in useDuplicateFlows hook

* Added refetch of folders when the flow is deleted or added

* Changed redirectToLastLocation to redirect to last folder also

* Added upload flow to folder tanstack and refetched folders on upload

* Added loading of current folder on display of empty component

* Removed refetching folder on file drop

* Removed unused code

* Fixed add new flow from header not redirecting correctly

* Fixed unused code

* Added undefined on setting current flow as empty

* Added disable top bar and make it be displayed on the top of an empty folder

* Fixed select all checked when deleting all flows
  • Loading branch information
lucaseduoli authored Aug 14, 2024
1 parent 1d8a24e commit 7658954
Show file tree
Hide file tree
Showing 44 changed files with 540 additions and 657 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Skeleton } from "@/components/ui/skeleton";

export function SidebarFolderSkeleton() {
return (
<div className="flex h-10 w-full shrink-0 animate-pulse cursor-pointer items-center gap-4 rounded-md border bg-background px-4 opacity-100 lg:min-w-full">
<Skeleton className="h-3 w-4 rounded-full" />
<Skeleton className="h-3 w-[40%]" />
</div>
);
}
Original file line number Diff line number Diff line change
@@ -1,33 +1,24 @@
import { usePostUploadFlowToFolder } from "@/controllers/API/queries/folders/use-post-upload-to-folder";
import useSaveFlow from "@/hooks/flows/use-save-flow";
import {
UPLOAD_ALERT_LIST,
WRONG_FILE_ERROR_ALERT,
} from "../../../constants/alerts_constants";
import { uploadFlowToFolder } from "../../../pages/MainPage/services";
import useAlertStore from "../../../stores/alertStore";
import useFlowsManagerStore from "../../../stores/flowsManagerStore";
import { useFolderStore } from "../../../stores/foldersStore";
import { addVersionToDuplicates } from "../../../utils/reactflowUtils";

const useFileDrop = (
folderId: string,
folderChangeCallback: (folderId: string) => void,
) => {
const useFileDrop = (folderId: string) => {
const setFolderDragging = useFolderStore((state) => state.setFolderDragging);
const setFolderIdDragging = useFolderStore(
(state) => state.setFolderIdDragging,
);

const setErrorData = useAlertStore((state) => state.setErrorData);
const refreshFolders = useFolderStore((state) => state.refreshFolders);
const flows = useFlowsManagerStore((state) => state.flows);
const saveFlow = useSaveFlow();

const triggerFolderChange = (folderId) => {
if (folderChangeCallback) {
folderChangeCallback(folderId);
}
};
const { mutate: uploadFlowToFolder } = usePostUploadFlowToFolder();
const handleFileDrop = async (e) => {
if (e.dataTransfer.types.some((type) => type === "Files")) {
if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {
Expand Down Expand Up @@ -121,10 +112,7 @@ const useFileDrop = (
setFolderDragging(false);
setFolderIdDragging("");

saveFlow(updatedFlow).then(() => {
refreshFolders();
triggerFolderChange(folderId);
});
saveFlow(updatedFlow);
};

const uploadFormData = (data) => {
Expand All @@ -133,10 +121,7 @@ const useFileDrop = (
setFolderDragging(false);
setFolderIdDragging("");

uploadFlowToFolder(formData, folderId).then(() => {
refreshFolders();
triggerFolderChange(folderId);
});
uploadFlowToFolder({ flows: formData, folderId });
};

return {
Expand Down
38 changes: 38 additions & 0 deletions src/frontend/src/components/folderSidebarComponent/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { useGetFoldersQuery } from "@/controllers/API/queries/folders/use-get-folders";
import { useLocation } from "react-router-dom";
import { FolderType } from "../../pages/MainPage/entities";
import { cn } from "../../utils/utils";
import HorizontalScrollFadeComponent from "../horizontalScrollFadeComponent";
import SideBarFoldersButtonsComponent from "./components/sideBarFolderButtons";

type SidebarNavProps = {
handleChangeFolder?: (id: string) => void;
handleDeleteFolder?: (item: FolderType) => void;
className?: string;
};

export default function FolderSidebarNav({
className,
handleChangeFolder,
handleDeleteFolder,
...props
}: SidebarNavProps) {
const location = useLocation();
const pathname = location.pathname;

const { data: folders, isPending } = useGetFoldersQuery();

return (
<nav className={cn(className)} {...props}>
<HorizontalScrollFadeComponent>
<SideBarFoldersButtonsComponent
loading={isPending || !folders}
pathname={pathname}
handleChangeFolder={handleChangeFolder}
handleDeleteFolder={handleDeleteFolder}
folders={folders}
/>
</HorizontalScrollFadeComponent>
</nav>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export const MenuBar = ({}: {}): JSX.Element => {
const currentSavedFlow = useFlowsManagerStore((state) => state.currentFlow);
const updatedAt = currentSavedFlow?.updated_at;
const onFlowPage = useFlowStore((state) => state.onFlowPage);
const setCurrentFlow = useFlowsManagerStore((state) => state.setCurrentFlow);

const changesNotSaved =
customStringify(currentFlow) !== customStringify(currentSavedFlow) &&
Expand All @@ -71,6 +72,7 @@ export const MenuBar = ({}: {}): JSX.Element => {
function handleAddFlow() {
try {
addFlow().then((id) => {
setCurrentFlow(undefined); // Reset current flow for useEffect of flowPage to update the current flow
navigate("/flow/" + id);
});
} catch (err) {
Expand Down
14 changes: 5 additions & 9 deletions src/frontend/src/components/headerComponent/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,12 @@ export default function Header(): JSX.Element {
}`;

const redirectToLastLocation = () => {
const lastFlowVisitedIndex = routeHistory
const lastVisitedIndex = routeHistory
.reverse()
.findIndex(
(path) => path.includes("/flow/") && path !== location.pathname,
);
.findIndex((path) => path !== location.pathname);

const lastFlowVisited = routeHistory[lastFlowVisitedIndex];
lastFlowVisited && !location.pathname.includes("/flow")
? navigate(lastFlowVisited)
: navigate("/all");
const lastFlowVisited = routeHistory[lastVisitedIndex];
lastFlowVisited ? navigate(lastFlowVisited) : navigate("/all");
};

const visitedFlowPathBefore = () => {
Expand Down Expand Up @@ -108,7 +104,7 @@ export default function Header(): JSX.Element {
</div>

<div className="round-button-div">
<Link to="/">
<Link to="/all">
<Button
className="gap-2"
variant={
Expand Down
28 changes: 1 addition & 27 deletions src/frontend/src/components/sidebarComponent/index.tsx
Original file line number Diff line number Diff line change
@@ -1,55 +1,29 @@
import { useLocation } from "react-router-dom";
import { FolderType } from "../../pages/MainPage/entities";
import { useFolderStore } from "../../stores/foldersStore";
import { cn } from "../../utils/utils";
import HorizontalScrollFadeComponent from "../horizontalScrollFadeComponent";
import SideBarButtonsComponent from "./components/sideBarButtons";
import SideBarFoldersButtonsComponent from "./components/sideBarFolderButtons";

type SidebarNavProps = {
items: {
href?: string;
title: string;
icon: React.ReactNode;
}[];
handleChangeFolder?: (id: string) => void;
handleEditFolder?: (item: FolderType) => void;
handleDeleteFolder?: (item: FolderType) => void;
className?: string;
};

export default function SidebarNav({
className,
items,
handleChangeFolder,
handleEditFolder,
handleDeleteFolder,
...props
}: SidebarNavProps) {
const location = useLocation();
const pathname = location.pathname;
const loadingFolders = useFolderStore((state) => state.isLoadingFolders);
const folders = useFolderStore((state) => state.folders);

const pathValues = ["folder", "components", "flows", "all"];
const isFolderPath = pathValues.some((value) => pathname.includes(value));

// Ensure all conditions are covered and provide a default case if necessary
const sidebarContent =
items.length > 0 ? (
<SideBarButtonsComponent items={items} pathname={pathname} />
) : !loadingFolders && folders?.length > 0 && isFolderPath ? (
<SideBarFoldersButtonsComponent
pathname={pathname}
handleChangeFolder={handleChangeFolder}
handleDeleteFolder={handleDeleteFolder}
/>
) : null;

return (
<nav className={cn(className)} {...props}>
<HorizontalScrollFadeComponent>
{sidebarContent!}
<SideBarButtonsComponent items={items} pathname={pathname} />
</HorizontalScrollFadeComponent>
</nav>
);
Expand Down
4 changes: 0 additions & 4 deletions src/frontend/src/contexts/authContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import useAuthStore from "@/stores/authStore";
import { createContext, useEffect, useState } from "react";
import Cookies from "universal-cookie";
import useAlertStore from "../stores/alertStore";
import { useFolderStore } from "../stores/foldersStore";
import { useStoreStore } from "../stores/storeStore";
import { Users } from "../types/api";
import { AuthContextType } from "../types/contexts/auth";
Expand Down Expand Up @@ -38,8 +37,6 @@ export function AuthProvider({ children }): React.ReactElement {
cookies.get(LANGFLOW_API_TOKEN),
);

const getFoldersApi = useFolderStore((state) => state.getFoldersApi);

const checkHasStore = useStoreStore((state) => state.checkHasStore);
const fetchApiData = useStoreStore((state) => state.fetchApiData);
const setIsAuthenticated = useAuthStore((state) => state.setIsAuthenticated);
Expand Down Expand Up @@ -68,7 +65,6 @@ export function AuthProvider({ children }): React.ReactElement {
setUserData(user);
const isSuperUser = user!.is_superuser;
useAuthStore.getState().setIsAdmin(isSuperUser);
getFoldersApi(true, true);
checkHasStore();
fetchApiData();
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const useDeleteDeleteFlows: useMutationFunctionType<
undefined,
IDeleteFlows
> = (options?) => {
const { mutate } = UseRequestProcessor();
const { mutate, queryClient } = UseRequestProcessor();

const deleteFlowsFn = async (payload: IDeleteFlows): Promise<any> => {
const response = await api.delete<any>(`${getURL("FLOWS")}/`, {
Expand All @@ -25,7 +25,12 @@ export const useDeleteDeleteFlows: useMutationFunctionType<
const mutation: UseMutationResult<IDeleteFlows, any, IDeleteFlows> = mutate(
["useLoginUser"],
deleteFlowsFn,
options,
{
...options,
onSettled: () => {
queryClient.refetchQueries({ queryKey: ["useGetFolder"] });
},
},
);

return mutation;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const usePatchUpdateFlow: useMutationFunctionType<
undefined,
IPatchUpdateFlow
> = (options?) => {
const { mutate } = UseRequestProcessor();
const { mutate, queryClient } = UseRequestProcessor();

const PatchUpdateFlowFn = async (payload: IPatchUpdateFlow): Promise<any> => {
const response = await api.patch(`${getURL("FLOWS")}/${payload.id}`, {
Expand All @@ -33,7 +33,14 @@ export const usePatchUpdateFlow: useMutationFunctionType<
};

const mutation: UseMutationResult<IPatchUpdateFlow, any, IPatchUpdateFlow> =
mutate(["usePatchUpdateFlow"], PatchUpdateFlowFn, options);
mutate(["usePatchUpdateFlow"], PatchUpdateFlowFn, {
...options,
onSettled: () => {
queryClient.refetchQueries({
queryKey: ["useGetFolder"],
});
},
});

return mutation;
};
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const usePostAddFlow: useMutationFunctionType<
undefined,
IPostAddFlow
> = (options?) => {
const { mutate } = UseRequestProcessor();
const { mutate, queryClient } = UseRequestProcessor();

const postAddFlowFn = async (payload: IPostAddFlow): Promise<any> => {
const response = await api.post(`${getURL("FLOWS")}/`, {
Expand All @@ -36,7 +36,12 @@ export const usePostAddFlow: useMutationFunctionType<
const mutation: UseMutationResult<IPostAddFlow, any, IPostAddFlow> = mutate(
["usePostAddFlow"],
postAddFlowFn,
options,
{
...options,
onSettled: () => {
queryClient.refetchQueries({ queryKey: ["useGetFolder"] });
},
},
);

return mutation;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const useDeleteFolders: useMutationFunctionType<
undefined,
DeleteFoldersParams
> = (options?) => {
const { mutate } = UseRequestProcessor();
const { mutate, queryClient } = UseRequestProcessor();

const deleteFolder = async ({
folder_id,
Expand All @@ -25,7 +25,12 @@ export const useDeleteFolders: useMutationFunctionType<
DeleteFoldersParams,
any,
DeleteFoldersParams
> = mutate(["useDeleteFolders"], deleteFolder, options);
> = mutate(["useDeleteFolders"], deleteFolder, {
...options,
onSettled: () => {
queryClient.refetchQueries({ queryKey: ["useGetFolders"] });
},
});

return mutation;
};
30 changes: 30 additions & 0 deletions src/frontend/src/controllers/API/queries/folders/use-get-folder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { FolderType } from "@/pages/MainPage/entities";
import { useQueryFunctionType } from "@/types/api";
import { api } from "../../api";
import { getURL } from "../../helpers/constants";
import { UseRequestProcessor } from "../../services/request-processor";

interface IGetFolder {
id: string;
}

export const useGetFolderQuery: useQueryFunctionType<IGetFolder, FolderType> = (
params,
options,
) => {
const { query } = UseRequestProcessor();

const getFolderFn = async (): Promise<FolderType> => {
const res = await api.get(`${getURL("FOLDERS")}/${params.id}`);
const data = res.data;

return data;
};

const queryResult = query(
["useGetFolder", { id: params.id }],
getFolderFn,
options,
);
return queryResult;
};
Loading

0 comments on commit 7658954

Please sign in to comment.