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