refactor: folder fetching, folder sidebar and fix various issues (#3344)
* 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
This commit is contained in:
parent
1d8a24eb86
commit
765895432e
44 changed files with 539 additions and 656 deletions
|
|
@ -8,7 +8,7 @@ import { createFileUpload } from "@/helpers/create-file-upload";
|
|||
import { getObjectsFromFilelist } from "@/helpers/get-objects-from-filelist";
|
||||
import useUploadFlow from "@/hooks/flows/use-upload-flow";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { FolderType } from "../../../../pages/MainPage/entities";
|
||||
import useAlertStore from "../../../../stores/alertStore";
|
||||
import useFlowsManagerStore from "../../../../stores/flowsManagerStore";
|
||||
|
|
@ -21,30 +21,32 @@ import IconComponent, {
|
|||
import { Button, buttonVariants } from "../../../ui/button";
|
||||
import { Input } from "../../../ui/input";
|
||||
import useFileDrop from "../../hooks/use-on-file-drop";
|
||||
import { SidebarFolderSkeleton } from "../sidebarFolderSkeleton";
|
||||
|
||||
type SideBarFoldersButtonsComponentProps = {
|
||||
pathname: string;
|
||||
handleChangeFolder?: (id: string) => void;
|
||||
handleDeleteFolder?: (item: FolderType) => void;
|
||||
folders: FolderType[] | undefined;
|
||||
loading?: boolean;
|
||||
};
|
||||
const SideBarFoldersButtonsComponent = ({
|
||||
pathname,
|
||||
handleChangeFolder,
|
||||
handleDeleteFolder,
|
||||
folders = [],
|
||||
loading,
|
||||
}: SideBarFoldersButtonsComponentProps) => {
|
||||
const refInput = useRef<HTMLInputElement>(null);
|
||||
const setFolders = useFolderStore((state) => state.setFolders);
|
||||
const folders = useFolderStore((state) => state.folders);
|
||||
const [foldersNames, setFoldersNames] = useState({});
|
||||
const takeSnapshot = useFlowsManagerStore((state) => state.takeSnapshot);
|
||||
const [editFolders, setEditFolderName] = useState(
|
||||
folders.map((obj) => ({ name: obj.name, edit: false })),
|
||||
folders.map((obj) => ({ name: obj.name, edit: false })) ?? [],
|
||||
);
|
||||
const currentFolder = pathname.split("/");
|
||||
const urlWithoutPath = pathname.split("/").length < 4;
|
||||
const myCollectionId = useFolderStore((state) => state.myCollectionId);
|
||||
const folderIdDragging = useFolderStore((state) => state.folderIdDragging);
|
||||
const refreshFolders = useFolderStore((state) => state.refreshFolders);
|
||||
|
||||
const checkPathName = (itemId: string) => {
|
||||
if (urlWithoutPath && itemId === myCollectionId) {
|
||||
|
|
@ -52,22 +54,12 @@ const SideBarFoldersButtonsComponent = ({
|
|||
}
|
||||
return currentFolder.includes(itemId);
|
||||
};
|
||||
const location = useLocation();
|
||||
const folderId = location?.state?.folderId ?? myCollectionId;
|
||||
const getFolderById = useFolderStore((state) => state.getFolderById);
|
||||
const folderId = useParams().folderId ?? myCollectionId ?? "";
|
||||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||
const setSuccessData = useAlertStore((state) => state.setSuccessData);
|
||||
const getFoldersApi = useFolderStore((state) => state.getFoldersApi);
|
||||
const uploadFlow = useUploadFlow();
|
||||
|
||||
const handleFolderChange = () => {
|
||||
getFolderById(folderId);
|
||||
};
|
||||
|
||||
const { dragOver, dragEnter, dragLeave, onDrop } = useFileDrop(
|
||||
folderId,
|
||||
handleFolderChange,
|
||||
);
|
||||
const { dragOver, dragEnter, dragLeave, onDrop } = useFileDrop(folderId);
|
||||
|
||||
const { mutate } = usePostUploadFolders();
|
||||
|
||||
|
|
@ -76,7 +68,6 @@ const SideBarFoldersButtonsComponent = ({
|
|||
getObjectsFromFilelist<any>(files).then((objects) => {
|
||||
if (objects.every((flow) => flow.data?.nodes)) {
|
||||
uploadFlow({ files }).then(() => {
|
||||
getFolderById(folderId);
|
||||
setSuccessData({
|
||||
title: "Uploaded successfully",
|
||||
});
|
||||
|
|
@ -89,7 +80,6 @@ const SideBarFoldersButtonsComponent = ({
|
|||
{ formData },
|
||||
{
|
||||
onSuccess: () => {
|
||||
getFoldersApi(true);
|
||||
setSuccessData({
|
||||
title: "Folder uploaded successfully.",
|
||||
});
|
||||
|
|
@ -146,20 +136,13 @@ const SideBarFoldersButtonsComponent = ({
|
|||
const { mutate: mutateUpdateFolder } = usePatchFolders();
|
||||
|
||||
function addNewFolder() {
|
||||
mutateAddFolder(
|
||||
{
|
||||
data: {
|
||||
name: "New Folder",
|
||||
parent_id: null,
|
||||
description: "",
|
||||
},
|
||||
mutateAddFolder({
|
||||
data: {
|
||||
name: "New Folder",
|
||||
parent_id: null,
|
||||
description: "",
|
||||
},
|
||||
{
|
||||
onSuccess: () => {
|
||||
refreshFolders();
|
||||
},
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function handleEditFolderName(e, name): void {
|
||||
|
|
@ -173,7 +156,7 @@ const SideBarFoldersButtonsComponent = ({
|
|||
}
|
||||
|
||||
useEffect(() => {
|
||||
folders.map((obj) => ({ name: obj.name, edit: false }));
|
||||
setEditFolderName(folders.map((obj) => ({ name: obj.name, edit: false })));
|
||||
}, [folders]);
|
||||
|
||||
const handleEditNameFolder = async (item) => {
|
||||
|
|
@ -210,7 +193,6 @@ const SideBarFoldersButtonsComponent = ({
|
|||
const updateFolders = [...folders];
|
||||
updateFolders[updatedFolderIndex] = updatedFolder;
|
||||
|
||||
setFolders(updateFolders);
|
||||
setFoldersNames({});
|
||||
setEditFolderName(
|
||||
folders.map((obj) => ({
|
||||
|
|
@ -255,156 +237,163 @@ const SideBarFoldersButtonsComponent = ({
|
|||
|
||||
<div className="flex gap-2 overflow-auto lg:h-[70vh] lg:flex-col">
|
||||
<>
|
||||
{folders.map((item, index) => {
|
||||
const editFolderName = editFolders?.filter(
|
||||
(folder) => folder.name === item.name,
|
||||
)[0];
|
||||
return (
|
||||
<div
|
||||
onDragOver={(e) => dragOver(e, item.id!)}
|
||||
onDragEnter={(e) => dragEnter(e, item.id!)}
|
||||
onDragLeave={dragLeave}
|
||||
onDrop={(e) => onDrop(e, item.id!)}
|
||||
key={item.id}
|
||||
data-testid={`sidebar-nav-${item.name}`}
|
||||
className={cn(
|
||||
buttonVariants({ variant: "ghost" }),
|
||||
checkPathName(item.id!)
|
||||
? "border border-border bg-muted hover:bg-muted"
|
||||
: "border hover:bg-transparent lg:border-transparent lg:hover:border-border",
|
||||
"group flex w-full shrink-0 cursor-pointer gap-2 opacity-100 lg:min-w-full",
|
||||
folderIdDragging === item.id! ? "bg-border" : "",
|
||||
)}
|
||||
onClick={() => handleChangeFolder!(item.id!)}
|
||||
>
|
||||
{!loading ? (
|
||||
folders.map((item, index) => {
|
||||
const editFolderName = editFolders?.filter(
|
||||
(folder) => folder.name === item.name,
|
||||
)[0];
|
||||
return (
|
||||
<div
|
||||
onDoubleClick={(event) => {
|
||||
if (item.name === "My Projects") {
|
||||
return;
|
||||
}
|
||||
onDragOver={(e) => dragOver(e, item.id!)}
|
||||
onDragEnter={(e) => dragEnter(e, item.id!)}
|
||||
onDragLeave={dragLeave}
|
||||
onDrop={(e) => onDrop(e, item.id!)}
|
||||
key={item.id}
|
||||
data-testid={`sidebar-nav-${item.name}`}
|
||||
className={cn(
|
||||
buttonVariants({ variant: "ghost" }),
|
||||
checkPathName(item.id!)
|
||||
? "border border-border bg-muted hover:bg-muted"
|
||||
: "border hover:bg-transparent lg:border-transparent lg:hover:border-border",
|
||||
"group flex w-full shrink-0 cursor-pointer gap-2 opacity-100 lg:min-w-full",
|
||||
folderIdDragging === item.id! ? "bg-border" : "",
|
||||
)}
|
||||
onClick={() => handleChangeFolder!(item.id!)}
|
||||
>
|
||||
<div
|
||||
onDoubleClick={(event) => {
|
||||
if (item.name === "My Projects") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!foldersNames[item.name]) {
|
||||
setFoldersNames({ [item.name]: item.name });
|
||||
}
|
||||
if (!foldersNames[item.name]) {
|
||||
setFoldersNames({ [item.name]: item.name });
|
||||
}
|
||||
|
||||
if (
|
||||
editFolders.find((obj) => obj.name === item.name)?.name
|
||||
) {
|
||||
const newEditFolders = editFolders.map((obj) => {
|
||||
if (obj.name === item.name) {
|
||||
return { name: item.name, edit: true };
|
||||
}
|
||||
return { name: obj.name, edit: false };
|
||||
});
|
||||
setEditFolderName(newEditFolders);
|
||||
if (
|
||||
editFolders.find((obj) => obj.name === item.name)?.name
|
||||
) {
|
||||
const newEditFolders = editFolders.map((obj) => {
|
||||
if (obj.name === item.name) {
|
||||
return { name: item.name, edit: true };
|
||||
}
|
||||
return { name: obj.name, edit: false };
|
||||
});
|
||||
setEditFolderName(newEditFolders);
|
||||
takeSnapshot();
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
setEditFolderName((old) => [
|
||||
...old,
|
||||
{ name: item.name, edit: true },
|
||||
]);
|
||||
setFoldersNames((oldFolder) => ({
|
||||
...oldFolder,
|
||||
[item.name]: item.name,
|
||||
}));
|
||||
takeSnapshot();
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
setEditFolderName((old) => [
|
||||
...old,
|
||||
{ name: item.name, edit: true },
|
||||
]);
|
||||
setFoldersNames((oldFolder) => ({
|
||||
...oldFolder,
|
||||
[item.name]: item.name,
|
||||
}));
|
||||
takeSnapshot();
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
}}
|
||||
className="flex w-full items-center gap-2"
|
||||
>
|
||||
<IconComponent
|
||||
name={"folder"}
|
||||
className="mr-2 w-4 flex-shrink-0 justify-start stroke-[1.5] opacity-100"
|
||||
/>
|
||||
{editFolderName?.edit ? (
|
||||
<div>
|
||||
<Input
|
||||
className="w-36"
|
||||
onChange={(e) => {
|
||||
handleEditFolderName(e, item.name);
|
||||
}}
|
||||
className="flex w-full items-center gap-2"
|
||||
>
|
||||
<IconComponent
|
||||
name={"folder"}
|
||||
className="mr-2 w-4 flex-shrink-0 justify-start stroke-[1.5] opacity-100"
|
||||
/>
|
||||
{editFolderName?.edit ? (
|
||||
<div>
|
||||
<Input
|
||||
className="w-36"
|
||||
onChange={(e) => {
|
||||
handleEditFolderName(e, item.name);
|
||||
}}
|
||||
ref={refInput}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Escape") {
|
||||
const newEditFolders = editFolders.map((obj) => {
|
||||
if (obj.name === item.name) {
|
||||
return { name: item.name, edit: false };
|
||||
}
|
||||
return { name: obj.name, edit: false };
|
||||
});
|
||||
setEditFolderName(newEditFolders);
|
||||
setFoldersNames({});
|
||||
setEditFolderName(
|
||||
folders.map((obj) => ({
|
||||
name: obj.name,
|
||||
edit: false,
|
||||
})),
|
||||
);
|
||||
}
|
||||
if (e.key === "Enter") {
|
||||
refInput.current?.blur();
|
||||
}
|
||||
handleKeyDown(e, e.key, "");
|
||||
}}
|
||||
autoFocus={true}
|
||||
onBlur={async () => {
|
||||
if (refInput.current?.value !== item.name) {
|
||||
handleEditNameFolder(item);
|
||||
} else {
|
||||
editFolderName.edit = false;
|
||||
}
|
||||
}}
|
||||
value={foldersNames[item.name]}
|
||||
id={`input-folder-${item.name}`}
|
||||
data-testid={`input-folder`}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<span className="block w-full truncate opacity-100">
|
||||
{item.name}
|
||||
</span>
|
||||
)}
|
||||
{index > 0 && (
|
||||
<Button
|
||||
data-testid="btn-delete-folder"
|
||||
className="hidden p-0 hover:bg-white group-hover:block hover:dark:bg-[#0c101a00]"
|
||||
onClick={(e) => {
|
||||
handleDeleteFolder!(item);
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}}
|
||||
ref={refInput}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Escape") {
|
||||
const newEditFolders = editFolders.map((obj) => {
|
||||
if (obj.name === item.name) {
|
||||
return { name: item.name, edit: false };
|
||||
}
|
||||
return { name: obj.name, edit: false };
|
||||
});
|
||||
setEditFolderName(newEditFolders);
|
||||
setFoldersNames({});
|
||||
setEditFolderName(
|
||||
folders.map((obj) => ({
|
||||
name: obj.name,
|
||||
edit: false,
|
||||
})),
|
||||
);
|
||||
}
|
||||
if (e.key === "Enter") {
|
||||
refInput.current?.blur();
|
||||
}
|
||||
handleKeyDown(e, e.key, "");
|
||||
}}
|
||||
autoFocus={true}
|
||||
onBlur={async () => {
|
||||
if (refInput.current?.value !== item.name) {
|
||||
handleEditNameFolder(item);
|
||||
} else {
|
||||
editFolderName.edit = false;
|
||||
}
|
||||
}}
|
||||
value={foldersNames[item.name]}
|
||||
id={`input-folder-${item.name}`}
|
||||
data-testid={`input-folder`}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<span className="block w-full truncate opacity-100">
|
||||
{item.name}
|
||||
</span>
|
||||
)}
|
||||
{index > 0 && (
|
||||
variant={"ghost"}
|
||||
size={"icon"}
|
||||
>
|
||||
<IconComponent
|
||||
name={"trash"}
|
||||
className="w-4 stroke-[1.5] p-0"
|
||||
/>
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
data-testid="btn-delete-folder"
|
||||
className="hidden p-0 hover:bg-white group-hover:block hover:dark:bg-[#0c101a00]"
|
||||
onClick={(e) => {
|
||||
handleDeleteFolder!(item);
|
||||
handleDownloadFolder(item.id!);
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}}
|
||||
variant={"ghost"}
|
||||
size={"icon"}
|
||||
unstyled
|
||||
>
|
||||
<IconComponent
|
||||
name={"trash"}
|
||||
className="w-4 stroke-[1.5] p-0"
|
||||
name={"Download"}
|
||||
className="w-4 stroke-[1.5] text-white"
|
||||
/>
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
className="hidden p-0 hover:bg-white group-hover:block hover:dark:bg-[#0c101a00]"
|
||||
onClick={(e) => {
|
||||
handleDownloadFolder(item.id!);
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}}
|
||||
unstyled
|
||||
>
|
||||
<IconComponent
|
||||
name={"Download"}
|
||||
className="w-4 stroke-[1.5] text-white"
|
||||
/>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
);
|
||||
})
|
||||
) : (
|
||||
<>
|
||||
<SidebarFolderSkeleton />
|
||||
<SidebarFolderSkeleton />
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
</div>
|
||||
</>
|
||||
|
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
|
@ -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) {
|
||||
|
|
@ -121,10 +112,7 @@ const useFileDrop = (
|
|||
setFolderDragging(false);
|
||||
setFolderIdDragging("");
|
||||
|
||||
saveFlow(updatedFlow).then(() => {
|
||||
refreshFolders();
|
||||
triggerFolderChange(folderId);
|
||||
});
|
||||
saveFlow(updatedFlow);
|
||||
};
|
||||
|
||||
const uploadFormData = (data) => {
|
||||
|
|
@ -133,10 +121,7 @@ const useFileDrop = (
|
|||
setFolderDragging(false);
|
||||
setFolderIdDragging("");
|
||||
|
||||
uploadFlowToFolder(formData, folderId).then(() => {
|
||||
refreshFolders();
|
||||
triggerFolderChange(folderId);
|
||||
});
|
||||
uploadFlowToFolder({ flows: formData, folderId });
|
||||
};
|
||||
|
||||
return {
|
||||
38
src/frontend/src/components/folderSidebarComponent/index.tsx
Normal file
38
src/frontend/src/components/folderSidebarComponent/index.tsx
Normal file
|
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
|
@ -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) &&
|
||||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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 = () => {
|
||||
|
|
@ -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={
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
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: {
|
||||
|
|
@ -12,44 +9,21 @@ type SidebarNavProps = {
|
|||
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>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
@ -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);
|
||||
|
|
@ -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();
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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")}/`, {
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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}`, {
|
||||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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")}/`, {
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ export const useDeleteFolders: useMutationFunctionType<
|
|||
undefined,
|
||||
DeleteFoldersParams
|
||||
> = (options?) => {
|
||||
const { mutate } = UseRequestProcessor();
|
||||
const { mutate, queryClient } = UseRequestProcessor();
|
||||
|
||||
const deleteFolder = async ({
|
||||
folder_id,
|
||||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
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";
|
||||
|
||||
export const useGetFoldersQuery: useQueryFunctionType<
|
||||
undefined,
|
||||
FolderType[]
|
||||
> = (options) => {
|
||||
const { query } = UseRequestProcessor();
|
||||
|
||||
const setStarterProjectId = useFolderStore(
|
||||
(state) => state.setStarterProjectId,
|
||||
);
|
||||
const setMyCollectionId = useFolderStore((state) => state.setMyCollectionId);
|
||||
|
||||
const getFoldersFn = async (): Promise<FolderType[]> => {
|
||||
const res = await api.get(`${getURL("FOLDERS")}/`);
|
||||
const data = res.data;
|
||||
|
||||
const foldersWithoutStarterProjects = data?.filter(
|
||||
(folder) => folder.name !== STARTER_FOLDER_NAME,
|
||||
);
|
||||
|
||||
const starterProjects = data?.find(
|
||||
(folder) => folder.name === STARTER_FOLDER_NAME,
|
||||
);
|
||||
|
||||
setStarterProjectId(starterProjects?.id ?? "");
|
||||
|
||||
const myCollectionId = data?.find((f) => f.name === DEFAULT_FOLDER)?.id;
|
||||
setMyCollectionId(myCollectionId);
|
||||
|
||||
const { refreshFlows } = useFlowsManagerStore.getState();
|
||||
const { getTypes } = useTypesStore.getState();
|
||||
|
||||
await refreshFlows();
|
||||
await getTypes();
|
||||
|
||||
return foldersWithoutStarterProjects;
|
||||
};
|
||||
|
||||
const queryResult = query(["useGetFolders"], getFoldersFn, options);
|
||||
return queryResult;
|
||||
};
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
import { AddFolderType } from "@/pages/MainPage/entities";
|
||||
import { useFolderStore } from "@/stores/foldersStore";
|
||||
import { useMutationFunctionType } from "@/types/api";
|
||||
import { api } from "../../api";
|
||||
import { getURL } from "../../helpers/constants";
|
||||
|
|
@ -14,7 +13,7 @@ export const usePatchFolders: useMutationFunctionType<
|
|||
undefined,
|
||||
IPatchPatchFolders
|
||||
> = (options?) => {
|
||||
const { mutate } = UseRequestProcessor();
|
||||
const { mutate, queryClient } = UseRequestProcessor();
|
||||
|
||||
const patchFoldersFn = async (
|
||||
newFolder: IPatchPatchFolders,
|
||||
|
|
@ -33,7 +32,12 @@ export const usePatchFolders: useMutationFunctionType<
|
|||
return res.data;
|
||||
};
|
||||
|
||||
const mutation = mutate(["usePatchFolders"], patchFoldersFn, options);
|
||||
const mutation = mutate(["usePatchFolders"], patchFoldersFn, {
|
||||
...options,
|
||||
onSettled: () => {
|
||||
queryClient.refetchQueries({ queryKey: ["useGetFolders"] });
|
||||
},
|
||||
});
|
||||
|
||||
return mutation;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
import { AddFolderType } from "@/pages/MainPage/entities";
|
||||
import useFlowsManagerStore from "@/stores/flowsManagerStore";
|
||||
import { useFolderStore } from "@/stores/foldersStore";
|
||||
import { Users, useMutationFunctionType } from "@/types/api";
|
||||
import { useMutationFunctionType } from "@/types/api";
|
||||
import { api } from "../../api";
|
||||
import { getURL } from "../../helpers/constants";
|
||||
import { UseRequestProcessor } from "../../services/request-processor";
|
||||
|
|
@ -14,7 +12,7 @@ export const usePostFolders: useMutationFunctionType<
|
|||
undefined,
|
||||
IPostAddFolders
|
||||
> = (options?) => {
|
||||
const { mutate } = UseRequestProcessor();
|
||||
const { mutate, queryClient } = UseRequestProcessor();
|
||||
|
||||
const addFoldersFn = async (newFolder: IPostAddFolders): Promise<void> => {
|
||||
const payload = {
|
||||
|
|
@ -28,7 +26,12 @@ export const usePostFolders: useMutationFunctionType<
|
|||
return res.data;
|
||||
};
|
||||
|
||||
const mutation = mutate(["usePostFolders"], addFoldersFn, options);
|
||||
const mutation = mutate(["usePostFolders"], addFoldersFn, {
|
||||
...options,
|
||||
onSettled: () => {
|
||||
queryClient.refetchQueries({ queryKey: ["useGetFolders"] });
|
||||
},
|
||||
});
|
||||
|
||||
return mutation;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ export const usePostUploadFolders: useMutationFunctionType<
|
|||
undefined,
|
||||
IPostAddUploadFolders
|
||||
> = (options?) => {
|
||||
const { mutate } = UseRequestProcessor();
|
||||
const { mutate, queryClient } = UseRequestProcessor();
|
||||
|
||||
const uploadFoldersFn = async (
|
||||
payload: IPostAddUploadFolders,
|
||||
|
|
@ -23,7 +23,12 @@ export const usePostUploadFolders: useMutationFunctionType<
|
|||
return res.data;
|
||||
};
|
||||
|
||||
const mutation = mutate(["usePostUploadFolders"], uploadFoldersFn, options);
|
||||
const mutation = mutate(["usePostUploadFolders"], uploadFoldersFn, {
|
||||
...options,
|
||||
onSettled: () => {
|
||||
queryClient.refetchQueries({ queryKey: ["useGetFolders"] });
|
||||
},
|
||||
});
|
||||
|
||||
return mutation;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
import { useMutationFunctionType } from "@/types/api";
|
||||
import { api } from "../../api";
|
||||
import { getURL } from "../../helpers/constants";
|
||||
import { UseRequestProcessor } from "../../services/request-processor";
|
||||
|
||||
interface IPostAddUploadFlowToFolder {
|
||||
flows: FormData;
|
||||
folderId: string;
|
||||
}
|
||||
|
||||
export const usePostUploadFlowToFolder: useMutationFunctionType<
|
||||
undefined,
|
||||
IPostAddUploadFlowToFolder
|
||||
> = (options?) => {
|
||||
const { mutate, queryClient } = UseRequestProcessor();
|
||||
|
||||
const uploadFlowToFolderFn = async (
|
||||
payload: IPostAddUploadFlowToFolder,
|
||||
): Promise<void> => {
|
||||
const res = await api.post(
|
||||
`${getURL("FLOWS")}/upload/?folder_id=${encodeURIComponent(payload.folderId)}`,
|
||||
payload.flows,
|
||||
);
|
||||
return res.data;
|
||||
};
|
||||
|
||||
const mutation = mutate(["usePostUploadFlowToFolder"], uploadFlowToFolderFn, {
|
||||
...options,
|
||||
onSettled: () => {
|
||||
queryClient.refetchQueries({ queryKey: ["useGetFolder"] });
|
||||
},
|
||||
});
|
||||
|
||||
return mutation;
|
||||
};
|
||||
|
|
@ -14,6 +14,7 @@ import {
|
|||
updateGroupRecursion,
|
||||
} from "@/utils/reactflowUtils";
|
||||
import { cloneDeep } from "lodash";
|
||||
import { useParams } from "react-router-dom";
|
||||
import useDeleteFlow from "./use-delete-flow";
|
||||
|
||||
const useAddFlow = () => {
|
||||
|
|
@ -26,7 +27,10 @@ const useAddFlow = () => {
|
|||
const flows = useFlowsManagerStore((state) => state.flows);
|
||||
const setFlows = useFlowsManagerStore((state) => state.setFlows);
|
||||
const deleteFlow = useDeleteFlow();
|
||||
const setIsLoading = useFlowsManagerStore((state) => state.setIsLoading);
|
||||
|
||||
const { folderId } = useParams();
|
||||
|
||||
const myCollectionId = useFolderStore((state) => state.myCollectionId);
|
||||
|
||||
const { mutate: postAddFlow } = usePostAddFlow();
|
||||
|
||||
|
|
@ -45,8 +49,7 @@ const useAddFlow = () => {
|
|||
);
|
||||
});
|
||||
// Create a new flow with a default name if no flow is provided.
|
||||
const folder_id = useFolderStore.getState().folderUrl;
|
||||
const my_collection_id = useFolderStore.getState().myCollectionId;
|
||||
const folder_id = folderId ?? myCollectionId ?? "";
|
||||
|
||||
if (params?.override && flow) {
|
||||
const flowId = flows?.find((f) => f.name === flow.name);
|
||||
|
|
@ -54,15 +57,11 @@ const useAddFlow = () => {
|
|||
await deleteFlow({ id: flowId.id });
|
||||
}
|
||||
}
|
||||
const newFlow = createNewFlow(
|
||||
flowData!,
|
||||
folder_id || my_collection_id!,
|
||||
flow,
|
||||
);
|
||||
const newFlow = createNewFlow(flowData!, folder_id, flow);
|
||||
|
||||
const newName = addVersionToDuplicates(newFlow, flows ?? []);
|
||||
newFlow.name = newName;
|
||||
newFlow.folder_id = useFolderStore.getState().folderUrl;
|
||||
newFlow.folder_id = folder_id;
|
||||
|
||||
postAddFlow(newFlow, {
|
||||
onSuccess: ({ id }) => {
|
||||
|
|
@ -80,7 +79,6 @@ const useAddFlow = () => {
|
|||
["saved_components"]: data,
|
||||
}),
|
||||
}));
|
||||
setIsLoading(false);
|
||||
resolve(id);
|
||||
},
|
||||
onError: (error) => {
|
||||
|
|
@ -98,7 +96,6 @@ const useAddFlow = () => {
|
|||
],
|
||||
});
|
||||
}
|
||||
setIsLoading(false);
|
||||
reject(error); // Re-throw the error so the caller can handle it if needed},
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import {
|
|||
const useDeleteFlow = () => {
|
||||
const flows = useFlowsManagerStore((state) => state.flows);
|
||||
const setFlows = useFlowsManagerStore((state) => state.setFlows);
|
||||
const setIsLoading = useFlowsManagerStore((state) => state.setIsLoading);
|
||||
|
||||
const { mutate } = useDeleteDeleteFlows();
|
||||
|
||||
|
|
@ -30,7 +29,6 @@ const useDeleteFlow = () => {
|
|||
(flows ?? []).filter((flow) => !id.includes(flow.id)),
|
||||
);
|
||||
setFlows(myFlows);
|
||||
setIsLoading(false);
|
||||
useTypesStore.setState((state) => ({
|
||||
data: { ...state.data, ["saved_components"]: data },
|
||||
ComponentFields: extractFieldsFromComponenents({
|
||||
|
|
|
|||
|
|
@ -1,25 +1,21 @@
|
|||
import useAddFlow from "@/hooks/flows/use-add-flow";
|
||||
import { useLocation, useNavigate } from "react-router-dom";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardTitle,
|
||||
} from "../../../../components/ui/card";
|
||||
import { useFolderStore } from "../../../../stores/foldersStore";
|
||||
|
||||
export default function NewFlowCardComponent() {
|
||||
const addFlow = useAddFlow();
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const folderId = location?.state?.folderId;
|
||||
const setFolderUrl = useFolderStore((state) => state.setFolderUrl);
|
||||
const { folderId } = useParams();
|
||||
|
||||
return (
|
||||
<Card
|
||||
onClick={() => {
|
||||
addFlow().then((id) => {
|
||||
setFolderUrl(folderId ?? "");
|
||||
navigate(`/flow/${id}${folderId ? `/folder/${folderId}` : ""}`);
|
||||
});
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/// <reference types="vite-plugin-svgr/client" />
|
||||
import { useLocation, useNavigate } from "react-router-dom";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import BlogPost from "../../../../assets/undraw_blog_post_re_fy5x.svg?react";
|
||||
import ChatBot from "../../../../assets/undraw_chat_bot_re_e2gj.svg?react";
|
||||
import PromptChaining from "../../../../assets/undraw_cloud_docs_re_xjht.svg?react";
|
||||
|
|
@ -26,12 +26,10 @@ export default function UndrawCardComponent({
|
|||
}: UndrawCardComponentProps): JSX.Element {
|
||||
const addFlow = useAddFlow();
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const folderId = location?.state?.folderId;
|
||||
const setFolderUrl = useFolderStore((state) => state.setFolderUrl);
|
||||
const { folderId } = useParams();
|
||||
const myCollectionId = useFolderStore((state) => state.myCollectionId);
|
||||
|
||||
const folderIdUrl = folderId || myCollectionId || "";
|
||||
const folderIdUrl = folderId ?? myCollectionId;
|
||||
|
||||
function selectImage() {
|
||||
switch (flow.name) {
|
||||
|
|
@ -143,7 +141,6 @@ export default function UndrawCardComponent({
|
|||
onClick={() => {
|
||||
updateIds(flow.data!);
|
||||
addFlow({ flow }).then((id) => {
|
||||
setFolderUrl(folderId ?? "");
|
||||
navigate(`/flow/${id}/folder/${folderIdUrl}`);
|
||||
});
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
import { useLoginUser } from "@/controllers/API/queries/auth";
|
||||
import useFlowsManagerStore from "@/stores/flowsManagerStore";
|
||||
import { useFolderStore } from "@/stores/foldersStore";
|
||||
import { useContext, useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { Button } from "../../../components/ui/button";
|
||||
import { Input } from "../../../components/ui/input";
|
||||
import { SIGNIN_ERROR_ALERT } from "../../../constants/alerts_constants";
|
||||
|
|
@ -16,14 +14,10 @@ import {
|
|||
} from "../../../types/components";
|
||||
|
||||
export default function LoginAdminPage() {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [inputState, setInputState] =
|
||||
useState<loginInputStateType>(CONTROL_LOGIN_STATE);
|
||||
const { login } = useContext(AuthContext);
|
||||
const setLoading = useAlertStore((state) => state.setLoading);
|
||||
|
||||
const setAllFlows = useFlowsManagerStore((state) => state.setAllFlows);
|
||||
const setSelectedFolder = useFolderStore((state) => state.setSelectedFolder);
|
||||
|
||||
const { password, username } = inputState;
|
||||
|
|
@ -44,7 +38,6 @@ export default function LoginAdminPage() {
|
|||
|
||||
mutate(user, {
|
||||
onSuccess: (res) => {
|
||||
setAllFlows([]);
|
||||
setSelectedFolder(null);
|
||||
|
||||
setLoading(true);
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import {
|
|||
import { useGetHealthQuery } from "@/controllers/API/queries/health";
|
||||
import useTrackLastVisitedPath from "@/hooks/use-track-last-visited-path";
|
||||
import useFlowsManagerStore from "@/stores/flowsManagerStore";
|
||||
import { useFolderStore } from "@/stores/foldersStore";
|
||||
import { cn } from "@/utils/utils";
|
||||
import { ErrorBoundary } from "react-error-boundary";
|
||||
import { Outlet } from "react-router-dom";
|
||||
|
|
@ -18,14 +17,12 @@ export function AppWrapperPage() {
|
|||
useTrackLastVisitedPath();
|
||||
|
||||
const isLoading = useFlowsManagerStore((state) => state.isLoading);
|
||||
const isLoadingFolders = useFolderStore((state) => state.isLoadingFolders);
|
||||
const {
|
||||
data: healthData,
|
||||
isFetching: fetchingHealth,
|
||||
isError: isErrorHealth,
|
||||
refetch,
|
||||
} = useGetHealthQuery();
|
||||
const isLoadingApplication = isLoading || isLoadingFolders;
|
||||
return (
|
||||
<div className="flex h-full flex-col">
|
||||
<ErrorBoundary
|
||||
|
|
@ -54,7 +51,7 @@ export function AppWrapperPage() {
|
|||
<div
|
||||
className={cn(
|
||||
"loading-page-panel absolute left-0 top-0 z-[999]",
|
||||
isLoadingApplication ? "" : "hidden",
|
||||
isLoading ? "" : "hidden",
|
||||
)}
|
||||
>
|
||||
<LoadingComponent remSize={50} />
|
||||
|
|
|
|||
|
|
@ -87,7 +87,6 @@ export default function Page({ view }: { view?: boolean }): JSX.Element {
|
|||
(state) => state.setLastCopiedSelection,
|
||||
);
|
||||
const onConnect = useFlowStore((state) => state.onConnect);
|
||||
const currentSavedFlow = useFlowsManagerStore((state) => state.currentFlow);
|
||||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||
const setNoticeData = useAlertStore((state) => state.setNoticeData);
|
||||
const updateCurrentFlow = useFlowStore((state) => state.updateCurrentFlow);
|
||||
|
|
@ -423,23 +422,10 @@ export default function Page({ view }: { view?: boolean }): JSX.Element {
|
|||
[],
|
||||
);
|
||||
|
||||
const onPaneClick = useCallback((flow) => {
|
||||
const onPaneClick = useCallback(() => {
|
||||
setFilterEdge([]);
|
||||
}, []);
|
||||
|
||||
function onMouseAction(edge: Edge, color: string): void {
|
||||
const edges = useFlowStore.getState().edges;
|
||||
const newEdges = _.cloneDeep(edges);
|
||||
const style = { stroke: color, transition: "stroke 0.25s" };
|
||||
const updatedEdges = newEdges.map((obj) => {
|
||||
if (obj.id === edge.id) {
|
||||
return { ...obj, style };
|
||||
}
|
||||
return obj;
|
||||
});
|
||||
setEdges(updatedEdges);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="h-full w-full" ref={reactFlowWrapper}>
|
||||
{showCanvas ? (
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import FeatureFlags from "@/../feature-config.json";
|
|||
import { useGetGlobalVariables } from "@/controllers/API/queries/variables";
|
||||
import useSaveFlow from "@/hooks/flows/use-save-flow";
|
||||
import { SaveChangesModal } from "@/modals/saveChangesModal";
|
||||
import { useTypesStore } from "@/stores/typesStore";
|
||||
import { customStringify } from "@/utils/reactflowUtils";
|
||||
import { useEffect } from "react";
|
||||
import { useBlocker, useNavigate, useParams } from "react-router-dom";
|
||||
|
|
@ -31,6 +32,9 @@ 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 setIsLoading = useFlowsManagerStore((state) => state.setIsLoading);
|
||||
const getTypes = useTypesStore((state) => state.getTypes);
|
||||
|
||||
const handleSave = () => {
|
||||
saveFlow().then(() => (blocker.proceed ? blocker.proceed() : null));
|
||||
|
|
@ -53,16 +57,24 @@ export default function FlowPage({ view }: { view?: boolean }): JSX.Element {
|
|||
|
||||
// Set flow tab id
|
||||
useEffect(() => {
|
||||
if (flows && currentFlowId === "") {
|
||||
const isAnExistingFlow = flows.find((flow) => flow.id === id);
|
||||
const awaitgetTypes = async () => {
|
||||
if (flows && currentFlowId === "") {
|
||||
const isAnExistingFlow = flows.find((flow) => flow.id === id);
|
||||
|
||||
if (!isAnExistingFlow) {
|
||||
navigate("/all");
|
||||
return;
|
||||
if (!isAnExistingFlow) {
|
||||
navigate("/all");
|
||||
return;
|
||||
}
|
||||
|
||||
setCurrentFlow(isAnExistingFlow);
|
||||
} else if (!flows) {
|
||||
setIsLoading(true);
|
||||
await refreshFlows();
|
||||
await getTypes();
|
||||
setIsLoading(false);
|
||||
}
|
||||
|
||||
setCurrentFlow(isAnExistingFlow);
|
||||
}
|
||||
};
|
||||
awaitgetTypes();
|
||||
}, [id, flows]);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -70,7 +82,7 @@ export default function FlowPage({ view }: { view?: boolean }): JSX.Element {
|
|||
|
||||
return () => {
|
||||
setOnFlowPage(false);
|
||||
setCurrentFlow();
|
||||
setCurrentFlow(undefined);
|
||||
};
|
||||
}, [id]);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { useLoginUser } from "@/controllers/API/queries/auth";
|
|||
import { useFolderStore } from "@/stores/foldersStore";
|
||||
import * as Form from "@radix-ui/react-form";
|
||||
import { useContext, useState } from "react";
|
||||
import { Link, useNavigate } from "react-router-dom";
|
||||
import { Link } from "react-router-dom";
|
||||
import InputComponent from "../../components/inputComponent";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import { Input } from "../../components/ui/input";
|
||||
|
|
@ -10,7 +10,6 @@ import { SIGNIN_ERROR_ALERT } from "../../constants/alerts_constants";
|
|||
import { CONTROL_LOGIN_STATE } from "../../constants/constants";
|
||||
import { AuthContext } from "../../contexts/authContext";
|
||||
import useAlertStore from "../../stores/alertStore";
|
||||
import useFlowsManagerStore from "../../stores/flowsManagerStore";
|
||||
import { LoginType } from "../../types/api";
|
||||
import {
|
||||
inputHandlerEventType,
|
||||
|
|
@ -23,10 +22,7 @@ export default function LoginPage(): JSX.Element {
|
|||
|
||||
const { password, username } = inputState;
|
||||
const { login } = useContext(AuthContext);
|
||||
const navigate = useNavigate();
|
||||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||
const setLoading = useFlowsManagerStore((state) => state.setIsLoading);
|
||||
const setAllFlows = useFlowsManagerStore((state) => state.setAllFlows);
|
||||
const setSelectedFolder = useFolderStore((state) => state.setSelectedFolder);
|
||||
|
||||
function handleInput({
|
||||
|
|
@ -45,10 +41,8 @@ export default function LoginPage(): JSX.Element {
|
|||
|
||||
mutate(user, {
|
||||
onSuccess: (data) => {
|
||||
setAllFlows([]);
|
||||
setSelectedFolder(null);
|
||||
|
||||
setLoading(true);
|
||||
login(data.access_token, "login");
|
||||
},
|
||||
onError: (error) => {
|
||||
|
|
|
|||
|
|
@ -1,24 +1,19 @@
|
|||
import { useFolderStore } from "@/stores/foldersStore";
|
||||
import React from "react";
|
||||
import { Link, useNavigate } from "react-router-dom";
|
||||
import { Link, useNavigate, useParams } from "react-router-dom";
|
||||
import CollectionCardComponent from "../../../../../../components/cardComponent";
|
||||
import IconComponent from "../../../../../../components/genericIconComponent";
|
||||
import { Button } from "../../../../../../components/ui/button";
|
||||
const CollectionCard = ({ item, type, isLoading, control }) => {
|
||||
const navigate = useNavigate();
|
||||
const isComponent = item.is_component ?? false;
|
||||
const editFlowLink = `/flow/${item.id}`;
|
||||
const editFlowButtonTestId = `edit-flow-button-${item.id}`;
|
||||
|
||||
const folderUrl = useFolderStore((state) => state.folderUrl);
|
||||
const myCollectionIdFolder = useFolderStore((state) => state.myCollectionId);
|
||||
const { folderId } = useParams();
|
||||
|
||||
const hasFolderUrl = folderUrl != null && folderUrl !== "";
|
||||
const currentFolderUrl = hasFolderUrl ? folderUrl : myCollectionIdFolder;
|
||||
const editFlowLink = `/flow/${item.id}${folderId ? `/folder/${folderId}` : ""}`;
|
||||
|
||||
const handleClick = () => {
|
||||
if (!isComponent) {
|
||||
navigate(editFlowLink, { state: { folderId: currentFolderUrl } });
|
||||
navigate(editFlowLink);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -5,13 +5,6 @@ const useDuplicateFlows = (
|
|||
selectedFlowsComponentsCards: string[],
|
||||
allFlows: any[],
|
||||
resetFilter: () => void,
|
||||
getFoldersApi: (
|
||||
refetch?: boolean,
|
||||
startupApplication?: boolean,
|
||||
) => Promise<void>,
|
||||
folderId: string,
|
||||
myCollectionId: string,
|
||||
getFolderById: (id: string) => void,
|
||||
setSuccessData: (data: { title: string }) => void,
|
||||
setSelectedFlowsComponentsCards: (
|
||||
selectedFlowsComponentsCards: string[],
|
||||
|
|
@ -27,10 +20,6 @@ const useDuplicateFlows = (
|
|||
),
|
||||
).then(() => {
|
||||
resetFilter();
|
||||
getFoldersApi(true);
|
||||
if (!folderId || folderId === myCollectionId) {
|
||||
getFolderById(folderId ? folderId : myCollectionId);
|
||||
}
|
||||
setSuccessData({ title: `${cardTypes} duplicated successfully` });
|
||||
setSelectedFlowsComponentsCards([]);
|
||||
handleSelectAll(false);
|
||||
|
|
@ -40,10 +29,6 @@ const useDuplicateFlows = (
|
|||
addFlow,
|
||||
allFlows,
|
||||
resetFilter,
|
||||
getFoldersApi,
|
||||
folderId,
|
||||
myCollectionId,
|
||||
getFolderById,
|
||||
setSuccessData,
|
||||
setSelectedFlowsComponentsCards,
|
||||
handleSelectAll,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
import { usePostDownloadMultipleFlows } from "@/controllers/API/queries/flows";
|
||||
import { useGetFolderQuery } from "@/controllers/API/queries/folders/use-get-folder";
|
||||
import { useGetFoldersQuery } from "@/controllers/API/queries/folders/use-get-folders";
|
||||
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";
|
||||
import { useLocation, useParams } from "react-router-dom";
|
||||
import CardsWrapComponent from "../../../../components/cardsWrapComponent";
|
||||
import PaginatorComponent from "../../../../components/paginatorComponent";
|
||||
import { SkeletonCardComponent } from "../../../../components/skeletonCardComponent";
|
||||
|
|
@ -30,12 +32,8 @@ export default function ComponentsComponent({
|
|||
type?: string;
|
||||
}) {
|
||||
const isLoading = useFlowsManagerStore((state) => state.isLoading);
|
||||
const setAllFlows = useFlowsManagerStore((state) => state.setAllFlows);
|
||||
const allFlows = useFlowsManagerStore((state) => state.allFlows);
|
||||
|
||||
const flowsFromFolder = useFolderStore(
|
||||
(state) => state.selectedFolder?.flows,
|
||||
);
|
||||
const { folderId } = useParams();
|
||||
|
||||
const setSuccessData = useAlertStore((state) => state.setSuccessData);
|
||||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||
|
|
@ -51,47 +49,51 @@ export default function ComponentsComponent({
|
|||
const selectedFlowsComponentsCards = useFlowsManagerStore(
|
||||
(state) => state.selectedFlowsComponentsCards,
|
||||
);
|
||||
const myCollectionId = useFolderStore((state) => state.myCollectionId);
|
||||
|
||||
const { data: currentFolder, isLoading: isLoadingCurrentFolder } =
|
||||
useGetFolderQuery({
|
||||
id: folderId ?? myCollectionId ?? "",
|
||||
});
|
||||
const flowsFromFolder = currentFolder?.flows ?? [];
|
||||
|
||||
const [filteredFlows, setFilteredFlows] =
|
||||
useState<FlowType[]>(flowsFromFolder);
|
||||
|
||||
const handleFileDrop = useFileDrop(type);
|
||||
const [pageSize, setPageSize] = useState(20);
|
||||
const [pageIndex, setPageIndex] = useState(1);
|
||||
const location = useLocation();
|
||||
const all: FlowType[] = sortFlows(allFlows, type);
|
||||
const all: FlowType[] = sortFlows(filteredFlows, type);
|
||||
const start = (pageIndex - 1) * pageSize;
|
||||
const end = start + pageSize;
|
||||
const data: FlowType[] = all?.slice(start, end);
|
||||
const location = useLocation();
|
||||
|
||||
const name = getNameByType(type);
|
||||
|
||||
const folderId = location?.state?.folderId;
|
||||
const getFolderById = useFolderStore((state) => state.getFolderById);
|
||||
const myCollectionId = useFolderStore((state) => state.myCollectionId);
|
||||
const getFoldersApi = useFolderStore((state) => state.getFoldersApi);
|
||||
const setFolderUrl = useFolderStore((state) => state.setFolderUrl);
|
||||
const isLoadingFolders = useFolderStore((state) => state.isLoadingFolders);
|
||||
const setSelectedFolder = useFolderStore((state) => state.setSelectedFolder);
|
||||
|
||||
const { isLoading: isLoadingFolders } = useGetFoldersQuery();
|
||||
|
||||
const [shouldSelectAll, setShouldSelectAll] = useState(true);
|
||||
|
||||
const cardTypes = useMemo(() => {
|
||||
if (window.location.pathname.includes("components")) {
|
||||
if (location.pathname.includes("components")) {
|
||||
return "Components";
|
||||
}
|
||||
if (window.location.pathname.includes("flows")) {
|
||||
if (location.pathname.includes("flows")) {
|
||||
return "Flows";
|
||||
}
|
||||
return "Items";
|
||||
}, [window.location]);
|
||||
}, [location]);
|
||||
|
||||
useEffect(() => {
|
||||
setFolderUrl(folderId ?? "");
|
||||
setSelectedFlowsComponentsCards([]);
|
||||
handleSelectAll(false);
|
||||
setShouldSelectAll(true);
|
||||
getFolderById(folderId ? folderId : myCollectionId);
|
||||
}, [location, folderId, myCollectionId]);
|
||||
}, [folderId, location, myCollectionId]);
|
||||
|
||||
useFilteredFlows(flowsFromFolder!, searchFlowsComponents, setAllFlows);
|
||||
useFilteredFlows(flowsFromFolder, searchFlowsComponents, setFilteredFlows);
|
||||
|
||||
const resetFilter = () => {
|
||||
setPageIndex(1);
|
||||
|
|
@ -111,12 +113,8 @@ export default function ComponentsComponent({
|
|||
|
||||
const { handleDuplicate } = useDuplicateFlows(
|
||||
selectedFlowsComponentsCards,
|
||||
allFlows,
|
||||
flowsFromFolder,
|
||||
resetFilter,
|
||||
getFoldersApi,
|
||||
folderId,
|
||||
myCollectionId!,
|
||||
getFolderById,
|
||||
setSuccessData,
|
||||
setSelectedFlowsComponentsCards,
|
||||
handleSelectAll,
|
||||
|
|
@ -133,7 +131,7 @@ export default function ComponentsComponent({
|
|||
},
|
||||
{
|
||||
onSuccess: (data) => {
|
||||
const selectedFlow = allFlows.find(
|
||||
const selectedFlow = flowsFromFolder.find(
|
||||
(flow) => flow.id === selectedFlowsComponentsCards[0],
|
||||
);
|
||||
|
||||
|
|
@ -190,18 +188,16 @@ export default function ComponentsComponent({
|
|||
const handleDeleteMultiple = () => {
|
||||
deleteFlow({ id: selectedFlowsComponentsCards })
|
||||
.then(() => {
|
||||
setAllFlows([]);
|
||||
setSelectedFolder(null);
|
||||
resetFilter();
|
||||
getFoldersApi(true);
|
||||
if (!folderId || folderId === myCollectionId) {
|
||||
getFolderById(folderId ? folderId : myCollectionId);
|
||||
}
|
||||
setSelectedFlowsComponentsCards([]);
|
||||
handleSelectAll(false);
|
||||
setShouldSelectAll(true);
|
||||
setSuccessData({
|
||||
title: "Selected items deleted successfully",
|
||||
});
|
||||
})
|
||||
.catch((e) => {
|
||||
.catch(() => {
|
||||
setErrorData({
|
||||
title: "Error deleting items",
|
||||
list: ["Please try again"],
|
||||
|
|
@ -216,28 +212,26 @@ export default function ComponentsComponent({
|
|||
type,
|
||||
);
|
||||
|
||||
const getTotalRowsCount = () => {
|
||||
if (type === "all") return allFlows?.length;
|
||||
|
||||
return allFlows?.filter(
|
||||
(f) => (f.is_component ?? false) === (type === "component"),
|
||||
)?.length;
|
||||
};
|
||||
const totalRowsCount = filteredFlows?.length;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex w-full gap-4 pb-5">
|
||||
{allFlows?.length > 0 && (
|
||||
<HeaderComponent
|
||||
shouldSelectAll={shouldSelectAll}
|
||||
setShouldSelectAll={setShouldSelectAll}
|
||||
handleDelete={() => handleSelectOptionsChange("delete")}
|
||||
handleSelectAll={handleSelectAll}
|
||||
handleDuplicate={() => handleSelectOptionsChange("duplicate")}
|
||||
handleExport={() => handleSelectOptionsChange("export")}
|
||||
disableFunctions={!(selectedFlowsComponentsCards?.length > 0)}
|
||||
/>
|
||||
)}
|
||||
<HeaderComponent
|
||||
disabled={
|
||||
isLoading ||
|
||||
isLoadingFolders ||
|
||||
isLoadingCurrentFolder ||
|
||||
data?.length === 0
|
||||
}
|
||||
shouldSelectAll={shouldSelectAll}
|
||||
setShouldSelectAll={setShouldSelectAll}
|
||||
handleDelete={() => handleSelectOptionsChange("delete")}
|
||||
handleSelectAll={handleSelectAll}
|
||||
handleDuplicate={() => handleSelectOptionsChange("duplicate")}
|
||||
handleExport={() => handleSelectOptionsChange("export")}
|
||||
disableFunctions={!(selectedFlowsComponentsCards?.length > 0)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<CardsWrapComponent
|
||||
|
|
@ -249,13 +243,16 @@ export default function ComponentsComponent({
|
|||
data-testid="cards-wrapper"
|
||||
>
|
||||
<div className="flex w-full flex-col gap-4">
|
||||
{!isLoading && !isLoadingFolders && data?.length === 0 ? (
|
||||
{!isLoading &&
|
||||
!isLoadingFolders &&
|
||||
!isLoadingCurrentFolder &&
|
||||
data?.length === 0 ? (
|
||||
<EmptyComponent />
|
||||
) : (
|
||||
<div className="grid w-full gap-4 md:grid-cols-2 lg:grid-cols-2">
|
||||
{isLoading === false &&
|
||||
data?.length > 0 &&
|
||||
isLoadingFolders === false ? (
|
||||
{data?.length > 0 &&
|
||||
isLoadingFolders === false &&
|
||||
isLoadingCurrentFolder === false ? (
|
||||
<>
|
||||
{data?.map((item) => (
|
||||
<FormProvider {...methods} key={item.id}>
|
||||
|
|
@ -286,7 +283,7 @@ export default function ComponentsComponent({
|
|||
pageIndex={pageIndex}
|
||||
pageSize={pageSize}
|
||||
rowsCount={[10, 20, 50, 100]}
|
||||
totalRowsCount={getTotalRowsCount()}
|
||||
totalRowsCount={totalRowsCount}
|
||||
paginate={(pageSize, pageIndex) => {
|
||||
setPageIndex(pageIndex);
|
||||
setPageSize(pageSize);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import { useState } from "react";
|
||||
import IconComponent from "../../../../components/genericIconComponent";
|
||||
import ShadTooltip from "../../../../components/shadTooltipComponent";
|
||||
import { Button } from "../../../../components/ui/button";
|
||||
|
|
@ -13,6 +12,7 @@ type HeaderComponentProps = {
|
|||
disableFunctions: boolean;
|
||||
setShouldSelectAll: (select) => void;
|
||||
shouldSelectAll: boolean;
|
||||
disabled: boolean;
|
||||
};
|
||||
|
||||
const HeaderComponent = ({
|
||||
|
|
@ -23,6 +23,7 @@ const HeaderComponent = ({
|
|||
disableFunctions,
|
||||
setShouldSelectAll,
|
||||
shouldSelectAll,
|
||||
disabled,
|
||||
}: HeaderComponentProps) => {
|
||||
const handleClick = () => {
|
||||
handleSelectAll(shouldSelectAll);
|
||||
|
|
@ -31,7 +32,12 @@ const HeaderComponent = ({
|
|||
|
||||
return (
|
||||
<>
|
||||
<div className="flex w-full items-center justify-between gap-4">
|
||||
<div
|
||||
className={cn(
|
||||
"flex w-full items-center justify-between gap-4",
|
||||
disabled ? "pointer-events-none opacity-50" : "",
|
||||
)}
|
||||
>
|
||||
<div className="flex items-center justify-self-start">
|
||||
<a onClick={handleClick} className="cursor-pointer text-sm">
|
||||
<div className="flex items-center space-x-2">
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { ChangeEvent, KeyboardEvent } from "react";
|
||||
import ForwardedIconComponent from "../../../../../../components/genericIconComponent";
|
||||
import { Input } from "../../../../../../components/ui/input";
|
||||
import useFlowsManagerStore from "../../../../../../stores/flowsManagerStore";
|
||||
|
||||
type InputSearchComponentProps = {
|
||||
loading: boolean;
|
||||
|
|
@ -21,9 +20,6 @@ const InputSearchComponent = ({
|
|||
onKeyDown,
|
||||
}: InputSearchComponentProps) => {
|
||||
const pagePath = window.location.pathname;
|
||||
const allFlows = useFlowsManagerStore((state) => state.allFlows);
|
||||
|
||||
const disableInputSearch = loading || !allFlows;
|
||||
|
||||
const getSearchPlaceholder = () => {
|
||||
if (pagePath.includes("flows")) {
|
||||
|
|
@ -40,7 +36,7 @@ const InputSearchComponent = ({
|
|||
<div className={`${divClasses ? divClasses : "relative h-12 w-[60%]"}`}>
|
||||
<Input
|
||||
data-testid="search-store-input"
|
||||
disabled={disableInputSearch}
|
||||
disabled={loading}
|
||||
placeholder={getSearchPlaceholder()}
|
||||
className="absolute h-12 pl-5 pr-12"
|
||||
onChange={onChange}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import { useEffect, useState } from "react";
|
||||
import { useEffect } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useFolderStore } from "../../../../../../stores/foldersStore";
|
||||
|
||||
type TabsSearchComponentProps = {
|
||||
tabsOptions: string[];
|
||||
|
|
@ -16,11 +15,6 @@ const TabsSearchComponent = ({
|
|||
tabActive,
|
||||
}: TabsSearchComponentProps) => {
|
||||
const navigate = useNavigate();
|
||||
const folderUrl = useFolderStore((state) => state.folderUrl);
|
||||
const myCollectionIdFolder = useFolderStore((state) => state.myCollectionId);
|
||||
|
||||
const hasFolderUrl = folderUrl != null && folderUrl !== "";
|
||||
const currentFolderUrl = hasFolderUrl ? folderUrl : myCollectionIdFolder;
|
||||
|
||||
const changeLocation = (tabOption) => {
|
||||
const location = window.location.pathname;
|
||||
|
|
@ -37,7 +31,7 @@ const TabsSearchComponent = ({
|
|||
break;
|
||||
}
|
||||
|
||||
navigate(newLocation, { state: { folderId: currentFolderUrl } });
|
||||
navigate(newLocation);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
|||
|
|
@ -1,16 +1,10 @@
|
|||
import useUploadFlow from "@/hooks/flows/use-upload-flow";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import { CONSOLE_ERROR_MSG } from "../../../constants/alerts_constants";
|
||||
import useAlertStore from "../../../stores/alertStore";
|
||||
import { useFolderStore } from "../../../stores/foldersStore";
|
||||
|
||||
const useFileDrop = (type?: string) => {
|
||||
const location = useLocation();
|
||||
const setSuccessData = useAlertStore((state) => state.setSuccessData);
|
||||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||
const getFolderById = useFolderStore((state) => state.getFolderById);
|
||||
const folderId = location?.state?.folderId;
|
||||
const myCollectionId = useFolderStore((state) => state.myCollectionId);
|
||||
const uploadFlow = useUploadFlow();
|
||||
|
||||
const handleFileDrop = (e) => {
|
||||
|
|
@ -26,7 +20,6 @@ const useFileDrop = (type?: string) => {
|
|||
setSuccessData({
|
||||
title: `All files uploaded successfully`,
|
||||
});
|
||||
getFolderById(folderId ? folderId : myCollectionId);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import FolderSidebarNav from "@/components/folderSidebarComponent";
|
||||
import { useDeleteFolders } from "@/controllers/API/queries/folders";
|
||||
import useAlertStore from "@/stores/alertStore";
|
||||
import { useState } from "react";
|
||||
import { Outlet, useLocation, useNavigate } from "react-router-dom";
|
||||
import DropdownButton from "../../../../components/dropdownButtonComponent";
|
||||
import PageLayout from "../../../../components/pageLayout";
|
||||
import SidebarNav from "../../../../components/sidebarComponent";
|
||||
import {
|
||||
MY_COLLECTION_DESC,
|
||||
USER_PROJECTS_HEADER,
|
||||
|
|
@ -12,13 +12,11 @@ import {
|
|||
import { useFolderStore } from "../../../../stores/foldersStore";
|
||||
import ModalsComponent from "../../components/modalsComponent";
|
||||
import useDropdownOptions from "../../hooks/use-dropdown-options";
|
||||
import { getFolderById } from "../../services";
|
||||
|
||||
export default function HomePage(): JSX.Element {
|
||||
const location = useLocation();
|
||||
const pathname = location.pathname;
|
||||
const [openModal, setOpenModal] = useState(false);
|
||||
const [openFolderModal, setOpenFolderModal] = useState(false);
|
||||
const [openDeleteFolderModal, setOpenDeleteFolderModal] = useState(false);
|
||||
const is_component = pathname === "/components";
|
||||
const setFolderToEdit = useFolderStore((state) => state.setFolderToEdit);
|
||||
|
|
@ -27,8 +25,6 @@ export default function HomePage(): JSX.Element {
|
|||
const setSuccessData = useAlertStore((state) => state.setSuccessData);
|
||||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||
const folderToEdit = useFolderStore((state) => state.folderToEdit);
|
||||
const myCollectionId = useFolderStore((state) => state.myCollectionId);
|
||||
const getFoldersApi = useFolderStore((state) => state.getFoldersApi);
|
||||
|
||||
const dropdownOptions = useDropdownOptions({
|
||||
navigate,
|
||||
|
|
@ -47,8 +43,6 @@ export default function HomePage(): JSX.Element {
|
|||
setSuccessData({
|
||||
title: "Folder deleted successfully.",
|
||||
});
|
||||
getFolderById(myCollectionId!);
|
||||
getFoldersApi(true);
|
||||
navigate("/all");
|
||||
},
|
||||
onError: (err) => {
|
||||
|
|
@ -80,14 +74,9 @@ export default function HomePage(): JSX.Element {
|
|||
>
|
||||
<div className="flex h-full w-full space-y-8 md:flex-col lg:flex-row lg:space-x-8 lg:space-y-0">
|
||||
<aside className="flex h-fit w-fit flex-col space-y-6">
|
||||
<SidebarNav
|
||||
items={[]}
|
||||
<FolderSidebarNav
|
||||
handleChangeFolder={(id: string) => {
|
||||
navigate(`all/folder/${id}`, { state: { folderId: id } });
|
||||
}}
|
||||
handleEditFolder={(item) => {
|
||||
setFolderToEdit(item);
|
||||
setOpenFolderModal(true);
|
||||
navigate(`all/folder/${id}`);
|
||||
}}
|
||||
handleDeleteFolder={(item) => {
|
||||
setFolderToEdit(item);
|
||||
|
|
|
|||
|
|
@ -1,41 +0,0 @@
|
|||
import { BASE_URL_API } from "../../../constants/constants";
|
||||
import { api } from "../../../controllers/API/api";
|
||||
import { FlowType } from "../../../types/flow";
|
||||
import { AddFolderType, FolderType } from "../entities";
|
||||
|
||||
export async function getFolders(): Promise<FolderType[]> {
|
||||
try {
|
||||
const response = await api.get(`${BASE_URL_API}folders/`);
|
||||
return response?.data;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export async function getFolderById(folderId: string): Promise<FolderType> {
|
||||
try {
|
||||
const response = await api.get(`${BASE_URL_API}folders/${folderId}`);
|
||||
return response?.data;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export async function uploadFlowToFolder(
|
||||
flows: FormData,
|
||||
folderId: string,
|
||||
): Promise<FlowType[]> {
|
||||
try {
|
||||
const url = `${BASE_URL_API}flows/upload/?folder_id=${encodeURIComponent(folderId)}`;
|
||||
|
||||
const response = await api.post(url, flows);
|
||||
|
||||
if (response?.status !== 201) {
|
||||
throw new Error(`HTTP error! status: ${response?.status}`);
|
||||
}
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
import { useGetGlobalVariables } from "@/controllers/API/queries/variables";
|
||||
import useFlowStore from "@/stores/flowStore";
|
||||
import { useTypesStore } from "@/stores/typesStore";
|
||||
import { useEffect } from "react";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import useFlowsManagerStore from "../../stores/flowsManagerStore";
|
||||
|
|
@ -15,19 +16,30 @@ export default function ViewPage() {
|
|||
|
||||
const flows = useFlowsManagerStore((state) => state.flows);
|
||||
const currentFlowId = useFlowsManagerStore((state) => state.currentFlowId);
|
||||
const refreshFlows = useFlowsManagerStore((state) => state.refreshFlows);
|
||||
const setIsLoading = useFlowsManagerStore((state) => state.setIsLoading);
|
||||
const getTypes = useTypesStore((state) => state.getTypes);
|
||||
|
||||
// Set flow tab id
|
||||
useEffect(() => {
|
||||
if (flows && currentFlowId === "") {
|
||||
const isAnExistingFlow = flows.find((flow) => flow.id === id);
|
||||
const awaitgetTypes = async () => {
|
||||
if (flows && currentFlowId === "") {
|
||||
const isAnExistingFlow = flows.find((flow) => flow.id === id);
|
||||
|
||||
if (!isAnExistingFlow) {
|
||||
navigate("/all");
|
||||
return;
|
||||
if (!isAnExistingFlow) {
|
||||
navigate("/all");
|
||||
return;
|
||||
}
|
||||
|
||||
setCurrentFlow(isAnExistingFlow);
|
||||
} else if (!flows) {
|
||||
setIsLoading(true);
|
||||
await refreshFlows();
|
||||
await getTypes();
|
||||
setIsLoading(false);
|
||||
}
|
||||
|
||||
setCurrentFlow(isAnExistingFlow);
|
||||
}
|
||||
};
|
||||
awaitgetTypes();
|
||||
}, [id, flows]);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -35,7 +47,7 @@ export default function ViewPage() {
|
|||
|
||||
return () => {
|
||||
setOnFlowPage(false);
|
||||
setCurrentFlow();
|
||||
setCurrentFlow(undefined);
|
||||
};
|
||||
}, [id]);
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import {
|
|||
Navigate,
|
||||
Route,
|
||||
} from "react-router-dom";
|
||||
import App from "./App";
|
||||
import { ProtectedAdminRoute } from "./components/authAdminGuard";
|
||||
import { ProtectedRoute } from "./components/authGuard";
|
||||
import { ProtectedLoginRoute } from "./components/authLoginGuard";
|
||||
|
|
@ -56,17 +55,34 @@ const router = createBrowserRouter(
|
|||
>
|
||||
<Route index element={<Navigate replace to={"all"} />} />
|
||||
<Route
|
||||
path="flows/*"
|
||||
path="flows/"
|
||||
element={<MyCollectionComponent key="flows" type="flow" />}
|
||||
/>
|
||||
>
|
||||
<Route
|
||||
path="folder/:folderId"
|
||||
element={<MyCollectionComponent key="flows" type="flow" />}
|
||||
/>
|
||||
</Route>
|
||||
<Route
|
||||
path="components/*"
|
||||
path="components/"
|
||||
element={<MyCollectionComponent key="components" type="component" />}
|
||||
/>
|
||||
>
|
||||
<Route
|
||||
path="folder/:folderId"
|
||||
element={
|
||||
<MyCollectionComponent key="components" type="component" />
|
||||
}
|
||||
/>
|
||||
</Route>
|
||||
<Route
|
||||
path="all/*"
|
||||
path="all/"
|
||||
element={<MyCollectionComponent key="all" type="all" />}
|
||||
/>
|
||||
>
|
||||
<Route
|
||||
path="folder/:folderId"
|
||||
element={<MyCollectionComponent key="all" type="all" />}
|
||||
/>
|
||||
</Route>
|
||||
</Route>
|
||||
<Route
|
||||
path="/settings"
|
||||
|
|
@ -122,7 +138,7 @@ const router = createBrowserRouter(
|
|||
</Route>
|
||||
<Route path="/flow/:id/">
|
||||
<Route
|
||||
path="*"
|
||||
path="folder/:folderId/"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<FlowPage />
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
// authStore.js
|
||||
import { LANGFLOW_ACCESS_TOKEN } from "@/constants/constants";
|
||||
import useFlowsManagerStore from "@/stores/flowsManagerStore";
|
||||
import { AuthStoreType } from "@/types/zustand/auth";
|
||||
import Cookies from "universal-cookie";
|
||||
import { create } from "zustand";
|
||||
import { useFolderStore } from "../stores/foldersStore";
|
||||
|
||||
const cookies = new Cookies();
|
||||
const useAuthStore = create<AuthStoreType>((set, get) => ({
|
||||
|
|
@ -40,33 +38,6 @@ const useAuthStore = create<AuthStoreType>((set, get) => ({
|
|||
|
||||
window.location.href = "/login";
|
||||
},
|
||||
// getUser: () => {
|
||||
// const setLoading = useAlertStore.getState().setLoading;
|
||||
// const getFoldersApi = useFolderStore.getState().getFoldersApi;
|
||||
// const checkHasStore = useStoreStore.getState().checkHasStore;
|
||||
// const fetchApiData = useStoreStore.getState().fetchApiData;
|
||||
|
||||
// getLoggedUser()
|
||||
// .then(async (user) => {
|
||||
// set({ userData: user, isAdmin: user.is_superuser });
|
||||
// getFoldersApi(true, true);
|
||||
// checkHasStore();
|
||||
// fetchApiData();
|
||||
// })
|
||||
// .catch((error) => {
|
||||
// setLoading(false);
|
||||
// });
|
||||
// },
|
||||
|
||||
// login: (newAccessToken) => {
|
||||
// set({ accessToken: newAccessToken, isAuthenticated: true });
|
||||
// get().getUser();
|
||||
// },
|
||||
|
||||
// storeApiKey: (apikey) => {
|
||||
// cookies.set('apikey_tkn_lflw', apikey, { path: '/' });
|
||||
// set({ apiKey: apikey });
|
||||
// },
|
||||
}));
|
||||
|
||||
export default useAuthStore;
|
||||
|
|
|
|||
|
|
@ -40,10 +40,6 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
|
|||
return get().flows?.find((flow) => flow.id === id);
|
||||
},
|
||||
flows: undefined,
|
||||
allFlows: [],
|
||||
setAllFlows: (allFlows: FlowType[]) => {
|
||||
set({ allFlows });
|
||||
},
|
||||
setFlows: (flows: FlowType[]) => {
|
||||
set({
|
||||
flows,
|
||||
|
|
@ -57,8 +53,6 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
|
|||
setIsLoading: (isLoading: boolean) => set({ isLoading }),
|
||||
refreshFlows: () => {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
set({ isLoading: true });
|
||||
|
||||
const starterFolderId = useFolderStore.getState().starterProjectId;
|
||||
|
||||
readFlowsFromDatabase()
|
||||
|
|
@ -82,7 +76,6 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
|
|||
["saved_components"]: data,
|
||||
}),
|
||||
}));
|
||||
set({ isLoading: false });
|
||||
resolve();
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,130 +1,16 @@
|
|||
import { create } from "zustand";
|
||||
import { DEFAULT_FOLDER, STARTER_FOLDER_NAME } from "../constants/constants";
|
||||
import { getFolderById, getFolders } from "../pages/MainPage/services";
|
||||
import { FoldersStoreType } from "../types/zustand/folders";
|
||||
import useFlowsManagerStore from "./flowsManagerStore";
|
||||
import { useTypesStore } from "./typesStore";
|
||||
|
||||
export const useFolderStore = create<FoldersStoreType>((set, get) => ({
|
||||
folders: [],
|
||||
getFoldersApi: (refetch = false, startupApplication: boolean = false) => {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
get().setIsLoadingFolders(true);
|
||||
if (get()?.folders.length === 0 || refetch === true) {
|
||||
getFolders().then(
|
||||
async (res) => {
|
||||
const foldersWithoutStarterProjects = res?.filter(
|
||||
(folder) => folder.name !== STARTER_FOLDER_NAME,
|
||||
);
|
||||
|
||||
const starterProjects = res?.find(
|
||||
(folder) => folder.name === STARTER_FOLDER_NAME,
|
||||
);
|
||||
|
||||
set({ starterProjectId: starterProjects?.id ?? "" });
|
||||
set({ folders: foldersWithoutStarterProjects });
|
||||
|
||||
const myCollectionId = res?.find(
|
||||
(f) => f.name === DEFAULT_FOLDER,
|
||||
)?.id;
|
||||
|
||||
set({ myCollectionId });
|
||||
|
||||
const { refreshFlows } = useFlowsManagerStore.getState();
|
||||
const { getTypes } = useTypesStore.getState();
|
||||
|
||||
if (refetch) {
|
||||
if (startupApplication) {
|
||||
await refreshFlows();
|
||||
await getTypes();
|
||||
get().setIsLoadingFolders(false);
|
||||
} else {
|
||||
refreshFlows();
|
||||
getTypes();
|
||||
get().setIsLoadingFolders(false);
|
||||
}
|
||||
}
|
||||
|
||||
resolve();
|
||||
},
|
||||
(error) => {
|
||||
set({ folders: [] });
|
||||
get().setIsLoadingFolders(false);
|
||||
reject(error);
|
||||
},
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
refreshFolders: () => {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
getFolders().then(
|
||||
async (res) => {
|
||||
const foldersWithoutStarterProjects = res?.filter(
|
||||
(folder) => folder.name !== STARTER_FOLDER_NAME,
|
||||
);
|
||||
|
||||
const starterProjects = res?.find(
|
||||
(folder) => folder.name === STARTER_FOLDER_NAME,
|
||||
);
|
||||
|
||||
set({ starterProjectId: starterProjects?.id ?? "" });
|
||||
set({ folders: foldersWithoutStarterProjects });
|
||||
|
||||
const myCollectionId = res?.find(
|
||||
(f) => f.name === DEFAULT_FOLDER,
|
||||
)?.id;
|
||||
|
||||
set({ myCollectionId });
|
||||
|
||||
resolve();
|
||||
},
|
||||
(error) => {
|
||||
set({ folders: [] });
|
||||
get().setIsLoadingFolders(false);
|
||||
reject(error);
|
||||
},
|
||||
);
|
||||
});
|
||||
},
|
||||
setFolders: (folders) => set(() => ({ folders: folders })),
|
||||
isLoadingFolders: false,
|
||||
setIsLoadingFolders: (isLoadingFolders) => set(() => ({ isLoadingFolders })),
|
||||
getFolderById: (id) => {
|
||||
if (id) {
|
||||
getFolderById(id).then((res) => {
|
||||
const setAllFlows = useFlowsManagerStore.getState().setAllFlows;
|
||||
setAllFlows(res?.flows);
|
||||
set({ selectedFolder: res });
|
||||
});
|
||||
}
|
||||
},
|
||||
selectedFolder: null,
|
||||
setSelectedFolder: (folder) => set(() => ({ selectedFolder: folder })),
|
||||
loadingById: false,
|
||||
getMyCollectionFolder: () => {
|
||||
const folders = get().folders;
|
||||
const myCollectionId = folders?.find((f) => f.name === DEFAULT_FOLDER)?.id;
|
||||
if (myCollectionId) {
|
||||
getFolderById(myCollectionId).then((res) => {
|
||||
set({ myCollectionFlows: res });
|
||||
});
|
||||
}
|
||||
},
|
||||
setMyCollectionFlow: (folder) => set(() => ({ myCollectionFlows: folder })),
|
||||
myCollectionFlows: null,
|
||||
setMyCollectionId: () => {
|
||||
const folders = get().folders;
|
||||
const myCollectionId = folders?.find((f) => f.name === DEFAULT_FOLDER)?.id;
|
||||
if (myCollectionId) {
|
||||
set({ myCollectionId });
|
||||
}
|
||||
setMyCollectionId: (myCollectionId) => {
|
||||
set({ myCollectionId });
|
||||
},
|
||||
myCollectionId: "",
|
||||
folderToEdit: null,
|
||||
setFolderToEdit: (folder) => set(() => ({ folderToEdit: folder })),
|
||||
folderUrl: "",
|
||||
setFolderUrl: (url) => set(() => ({ folderUrl: url })),
|
||||
folderDragging: false,
|
||||
setFolderDragging: (folder) => set(() => ({ folderDragging: folder })),
|
||||
folderIdDragging: "",
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ export const useTypesStore = create<TypesStoreType>((set, get) => ({
|
|||
getTypes: (force_refresh: boolean = false) => {
|
||||
return new Promise<void>(async (resolve, reject) => {
|
||||
const setLoading = useFlowsManagerStore.getState().setIsLoading;
|
||||
setLoading(true);
|
||||
getAll(force_refresh)
|
||||
.then((response) => {
|
||||
const data = response?.data;
|
||||
|
|
@ -38,7 +37,6 @@ export const useTypesStore = create<TypesStoreType>((set, get) => ({
|
|||
}),
|
||||
templates: templatesGenerator(data),
|
||||
}));
|
||||
setLoading(false);
|
||||
resolve();
|
||||
})
|
||||
.catch((error) => {
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@ import { FlowType } from "../../flow";
|
|||
export type FlowsManagerStoreType = {
|
||||
getFlowById: (id: string) => FlowType | undefined;
|
||||
flows: Array<FlowType> | undefined;
|
||||
allFlows: Array<FlowType>;
|
||||
setAllFlows: (flows: FlowType[]) => void;
|
||||
setFlows: (flows: FlowType[]) => void;
|
||||
currentFlow: FlowType | undefined;
|
||||
currentFlowId: string;
|
||||
|
|
|
|||
|
|
@ -1,30 +1,16 @@
|
|||
import { FolderType } from "../../../pages/MainPage/entities";
|
||||
|
||||
export type FoldersStoreType = {
|
||||
folders: FolderType[];
|
||||
getFoldersApi: (
|
||||
refetch?: boolean,
|
||||
startupApplication?: boolean,
|
||||
) => Promise<void>;
|
||||
setFolders: (folders: FolderType[]) => void;
|
||||
isLoadingFolders: boolean;
|
||||
setIsLoadingFolders: (isLoadingFolders: boolean) => void;
|
||||
selectedFolder: FolderType | null;
|
||||
setSelectedFolder: (folder: FolderType | null) => void;
|
||||
getFolderById: (id: string) => void;
|
||||
getMyCollectionFolder: () => void;
|
||||
myCollectionFlows: FolderType | null;
|
||||
myCollectionId: string | null;
|
||||
setMyCollectionId: () => void;
|
||||
setMyCollectionId: (value: string) => void;
|
||||
folderToEdit: FolderType | null;
|
||||
setFolderToEdit: (folder: FolderType | null) => void;
|
||||
folderUrl: string;
|
||||
setFolderUrl: (folderUrl: string) => void;
|
||||
folderDragging: boolean;
|
||||
setFolderDragging: (set: boolean) => void;
|
||||
folderIdDragging: string;
|
||||
setFolderIdDragging: (id: string) => void;
|
||||
starterProjectId: string;
|
||||
setStarterProjectId: (id: string) => void;
|
||||
refreshFolders: () => void;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue