+ {isDragging ? (
+ <>
+
+ Drop your flow here
+ >
+ ) : (
+
+ {isLoading && flows.length == 0 ? (
+ <>
+
+
+
+
+ >
+ ) : (
+ flows
+ .filter((flow) => !flow.is_component)
+ .map((flow, idx) => (
+
+
+
+ }
+ onDelete={() => {
+ removeFlow(flow.id);
+ }}
+ />
+ ))
+ )}
+
+ )}
+
+ );
+}
diff --git a/src/frontend/src/pages/MainPage/components/flows/index.tsx b/src/frontend/src/pages/MainPage/components/flows/index.tsx
new file mode 100644
index 000000000..6e0a2ef22
--- /dev/null
+++ b/src/frontend/src/pages/MainPage/components/flows/index.tsx
@@ -0,0 +1,133 @@
+import { useContext, useEffect, useState } from "react";
+import { Link, useNavigate } from "react-router-dom";
+import { CardComponent } from "../../../../components/cardComponent";
+import IconComponent from "../../../../components/genericIconComponent";
+import { SkeletonCardComponent } from "../../../../components/skeletonCardComponent";
+import { Button } from "../../../../components/ui/button";
+import { alertContext } from "../../../../contexts/alertContext";
+import { TabsContext } from "../../../../contexts/tabsContext";
+
+export default function FlowsComponent() {
+ const {
+ flows,
+ setTabId,
+ downloadFlows,
+ uploadFlows,
+ addFlow,
+ removeFlow,
+ uploadFlow,
+ isLoading,
+ } = useContext(TabsContext);
+ const { setErrorData } = useContext(alertContext);
+ const dropdownOptions = [
+ {
+ name: "Import from JSON",
+ onBtnClick: () =>
+ uploadFlow(true).then((id) => {
+ navigate("/flow/" + id);
+ }),
+ },
+ ];
+
+ // Set a null id
+ useEffect(() => {
+ setTabId("");
+ }, []);
+ const navigate = useNavigate();
+
+ const [isDragging, setIsDragging] = useState(false);
+
+ const dragOver = (e) => {
+ e.preventDefault();
+ if (e.dataTransfer.types.some((types) => types === "Files")) {
+ setIsDragging(true);
+ }
+ };
+
+ const dragEnter = (e) => {
+ if (e.dataTransfer.types.some((types) => types === "Files")) {
+ setIsDragging(true);
+ }
+ e.preventDefault();
+ };
+
+ const dragLeave = () => {
+ setIsDragging(false);
+ };
+
+ const fileDrop = (e) => {
+ e.preventDefault();
+ setIsDragging(false);
+ if (e.dataTransfer.types.some((types) => types === "Files")) {
+ if (e.dataTransfer.files.item(0).type === "application/json") {
+ uploadFlow(true, e.dataTransfer.files.item(0)!);
+ } else {
+ setErrorData({
+ title: "Invalid file type",
+ list: ["Please upload a JSON file"],
+ });
+ }
+ }
+ };
+ return (
+
+ {isDragging ? (
+ <>
+
+ Drop your flow here
+ >
+ ) : (
+
+ {isLoading && flows.length == 0 ? (
+ <>
+
+
+
+
+ >
+ ) : (
+ flows
+ .filter((flow) => !flow.is_component)
+ .map((flow, idx) => (
+
+
+
+ }
+ onDelete={() => {
+ removeFlow(flow.id);
+ }}
+ />
+ ))
+ )}
+
+ )}
+
+ );
+}
diff --git a/src/frontend/src/pages/MainPage/index.tsx b/src/frontend/src/pages/MainPage/index.tsx
index 441363a27..2138fc9db 100644
--- a/src/frontend/src/pages/MainPage/index.tsx
+++ b/src/frontend/src/pages/MainPage/index.tsx
@@ -1,11 +1,11 @@
import { useContext, useEffect, useState } from "react";
-import { Link, useNavigate } from "react-router-dom";
+import { Outlet, useNavigate } from "react-router-dom";
import DropdownButton from "../../components/DropdownButtonComponent";
-import { CardComponent } from "../../components/cardComponent";
import IconComponent from "../../components/genericIconComponent";
import Header from "../../components/headerComponent";
-import { SkeletonCardComponent } from "../../components/skeletonCardComponent";
+import SidebarNav from "../../components/sidebarComponent";
import { Button } from "../../components/ui/button";
+import { Separator } from "../../components/ui/separator";
import { USER_PROJECTS_HEADER } from "../../constants/constants";
import { alertContext } from "../../contexts/alertContext";
import { TabsContext } from "../../contexts/tabsContext";
@@ -30,6 +30,16 @@ export default function HomePage(): JSX.Element {
}),
},
];
+ const sidebarNavItems = [
+ {
+ title: "Flows",
+ href: "/flows",
+ },
+ {
+ title: "Components",
+ href: "/components",
+ },
+ ];
// Set a null id
useEffect(() => {
@@ -115,66 +125,15 @@ export default function HomePage(): JSX.Element {
- {isDragging ? (
- <>
-
- Drop your flow here
- >
- ) : (
-
- {isLoading && flows.length == 0 ? (
- <>
-
-
-
-
- >
- ) : (
- flows
- .filter((flow) => !flow.is_component)
- .map((flow, idx) => (
-
-
-
- }
- onDelete={() => {
- removeFlow(flow.id);
- }}
- />
- ))
- )}
-
- )}
+
+
>
diff --git a/src/frontend/src/routes.tsx b/src/frontend/src/routes.tsx
index 75aa2d436..1ef18f3c6 100644
--- a/src/frontend/src/routes.tsx
+++ b/src/frontend/src/routes.tsx
@@ -9,6 +9,8 @@ import ApiKeysPage from "./pages/ApiKeysPage";
import CommunityPage from "./pages/CommunityPage";
import FlowPage from "./pages/FlowPage";
import HomePage from "./pages/MainPage";
+import ComponentsComponent from "./pages/MainPage/components/components";
+import FlowsComponent from "./pages/MainPage/components/flows";
import ProfileSettingsPage from "./pages/ProfileSettingsPage";
import StorePage from "./pages/StorePage";
import ViewPage from "./pages/ViewPage";
@@ -26,7 +28,10 @@ const Router = () => {