Modularized components page and made it similar to LangStore
This commit is contained in:
parent
d07090f27c
commit
422e4bd5a0
6 changed files with 164 additions and 154 deletions
|
|
@ -1,16 +1,13 @@
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import IconComponent from "../../components/genericIconComponent";
|
import IconComponent from "../../components/genericIconComponent";
|
||||||
import { SkeletonCardComponent } from "../skeletonCardComponent";
|
|
||||||
|
|
||||||
export default function CardsWrapComponent({
|
export default function CardsWrapComponent({
|
||||||
onFileDrop,
|
onFileDrop,
|
||||||
children,
|
children,
|
||||||
isLoading,
|
|
||||||
dragMessage,
|
dragMessage,
|
||||||
}: {
|
}: {
|
||||||
onFileDrop?: (e: any) => void;
|
onFileDrop?: (e: any) => void;
|
||||||
children: JSX.Element | JSX.Element[];
|
children: JSX.Element | JSX.Element[];
|
||||||
isLoading: boolean;
|
|
||||||
dragMessage?: string;
|
dragMessage?: string;
|
||||||
}) {
|
}) {
|
||||||
const [isDragging, setIsDragging] = useState(false);
|
const [isDragging, setIsDragging] = useState(false);
|
||||||
|
|
@ -59,17 +56,7 @@ export default function CardsWrapComponent({
|
||||||
{dragMessage ? dragMessage : "Drop your file here"}
|
{dragMessage ? dragMessage : "Drop your file here"}
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<div className="main-page-flows-display">
|
children
|
||||||
{isLoading ? (
|
|
||||||
<>
|
|
||||||
<SkeletonCardComponent />
|
|
||||||
<SkeletonCardComponent />
|
|
||||||
<SkeletonCardComponent />
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
children
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ export default function PageLayout({
|
||||||
<div className="flex h-screen w-full flex-col">
|
<div className="flex h-screen w-full flex-col">
|
||||||
<Header />
|
<Header />
|
||||||
<div className="flex h-full w-full flex-col justify-between overflow-auto bg-background px-16">
|
<div className="flex h-full w-full flex-col justify-between overflow-auto bg-background px-16">
|
||||||
<div className="flex w-full items-center justify-between space-y-0.5 py-8 pb-2">
|
<div className="flex w-full items-center justify-between gap-4 space-y-0.5 py-8 pb-2">
|
||||||
<div className="flex w-full flex-col">
|
<div className="flex w-full flex-col">
|
||||||
<h2 className="text-2xl font-bold tracking-tight">{title}</h2>
|
<h2 className="text-2xl font-bold tracking-tight">{title}</h2>
|
||||||
<p className="text-muted-foreground">{description}</p>
|
<p className="text-muted-foreground">{description}</p>
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,43 @@
|
||||||
import { useContext } from "react";
|
import { useContext, useEffect, useState } from "react";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import PaginatorComponent from "../../../../components/PaginatorComponent";
|
||||||
import CollectionCardComponent from "../../../../components/cardComponent";
|
import CollectionCardComponent from "../../../../components/cardComponent";
|
||||||
import CardsWrapComponent from "../../../../components/cardsWrapComponent";
|
import CardsWrapComponent from "../../../../components/cardsWrapComponent";
|
||||||
|
import IconComponent from "../../../../components/genericIconComponent";
|
||||||
|
import { SkeletonCardComponent } from "../../../../components/skeletonCardComponent";
|
||||||
|
import { Button } from "../../../../components/ui/button";
|
||||||
import { alertContext } from "../../../../contexts/alertContext";
|
import { alertContext } from "../../../../contexts/alertContext";
|
||||||
import { FlowsContext } from "../../../../contexts/flowsContext";
|
import { FlowsContext } from "../../../../contexts/flowsContext";
|
||||||
|
import { FlowType } from "../../../../types/flow";
|
||||||
|
|
||||||
export default function ComponentsComponent() {
|
export default function ComponentsComponent({
|
||||||
|
is_component = true,
|
||||||
|
}: {
|
||||||
|
is_component?: boolean;
|
||||||
|
}) {
|
||||||
const { flows, removeFlow, uploadFlow, isLoading } = useContext(FlowsContext);
|
const { flows, removeFlow, uploadFlow, isLoading } = useContext(FlowsContext);
|
||||||
const { setErrorData } = useContext(alertContext);
|
const { setErrorData } = useContext(alertContext);
|
||||||
|
const [pageSize, setPageSize] = useState(10);
|
||||||
|
const [pageIndex, setPageIndex] = useState(1);
|
||||||
|
const [allData, setAllData] = useState(
|
||||||
|
flows.filter((f) => f.is_component === is_component)
|
||||||
|
);
|
||||||
|
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setAllData(flows.filter((f) => f.is_component === is_component));
|
||||||
|
}, [flows]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const start = (pageIndex - 1) * pageSize;
|
||||||
|
const end = start + pageSize;
|
||||||
|
setData(allData.slice(start, end));
|
||||||
|
}, [pageIndex, pageSize, allData]);
|
||||||
|
|
||||||
|
const [data, setData] = useState<FlowType[]>([]);
|
||||||
|
|
||||||
|
const name = is_component ? "Component" : "Flow";
|
||||||
|
|
||||||
const onFileDrop = (e) => {
|
const onFileDrop = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
@ -25,20 +56,74 @@ export default function ComponentsComponent() {
|
||||||
return (
|
return (
|
||||||
<CardsWrapComponent
|
<CardsWrapComponent
|
||||||
onFileDrop={onFileDrop}
|
onFileDrop={onFileDrop}
|
||||||
isLoading={isLoading && flows.length == 0}
|
dragMessage={`Drag your ${name} here`}
|
||||||
dragMessage={"Drop your component here"}
|
|
||||||
>
|
>
|
||||||
{flows
|
<div className="flex h-full w-full flex-col justify-between">
|
||||||
.filter((flow) => flow.is_component)
|
<div className="flex w-full flex-col gap-4">
|
||||||
.map((flow, idx) => (
|
<div className="grid w-full gap-4 md:grid-cols-2 lg:grid-cols-2">
|
||||||
<CollectionCardComponent
|
{!isLoading || data?.length > 0 ? (
|
||||||
key={idx}
|
data
|
||||||
data={flow}
|
?.sort(
|
||||||
onDelete={() => {
|
(a, b) =>
|
||||||
removeFlow(flow.id);
|
new Date(b?.date_created!).getTime() -
|
||||||
}}
|
new Date(a?.date_created!).getTime()
|
||||||
/>
|
)
|
||||||
))}
|
.map((item, idx) => (
|
||||||
|
<CollectionCardComponent
|
||||||
|
onDelete={() => {
|
||||||
|
removeFlow(item.id);
|
||||||
|
}}
|
||||||
|
key={idx}
|
||||||
|
data={item}
|
||||||
|
disabled={isLoading}
|
||||||
|
button={
|
||||||
|
!is_component ? (
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
className="whitespace-nowrap "
|
||||||
|
onClick={() => {
|
||||||
|
navigate("/flow/" + item.id);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IconComponent
|
||||||
|
name="ExternalLink"
|
||||||
|
className="main-page-nav-button"
|
||||||
|
/>
|
||||||
|
Edit Flow
|
||||||
|
</Button>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
) : !isLoading && data?.length === 0 ? (
|
||||||
|
<>You haven't created {name}s yet.</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<SkeletonCardComponent />
|
||||||
|
<SkeletonCardComponent />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{!isLoading && allData.length > 0 && (
|
||||||
|
<div className="relative py-6">
|
||||||
|
<PaginatorComponent
|
||||||
|
storeComponent={true}
|
||||||
|
pageIndex={pageIndex}
|
||||||
|
pageSize={pageSize}
|
||||||
|
rowsCount={[10, 20, 50, 100]}
|
||||||
|
totalRowsCount={allData.length}
|
||||||
|
paginate={(pageSize, pageIndex) => {
|
||||||
|
setPageIndex(pageIndex);
|
||||||
|
setPageSize(pageSize);
|
||||||
|
}}
|
||||||
|
></PaginatorComponent>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</CardsWrapComponent>
|
</CardsWrapComponent>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
import { useContext } from "react";
|
|
||||||
import { Link } from "react-router-dom";
|
|
||||||
import CollectionCardComponent from "../../../../components/cardComponent";
|
|
||||||
import CardsWrapComponent from "../../../../components/cardsWrapComponent";
|
|
||||||
import IconComponent from "../../../../components/genericIconComponent";
|
|
||||||
import { Button } from "../../../../components/ui/button";
|
|
||||||
import { alertContext } from "../../../../contexts/alertContext";
|
|
||||||
import { FlowsContext } from "../../../../contexts/flowsContext";
|
|
||||||
|
|
||||||
export default function FlowsComponent() {
|
|
||||||
const { uploadFlow, removeFlow, flows, isLoading } = useContext(FlowsContext);
|
|
||||||
const { setErrorData } = useContext(alertContext);
|
|
||||||
|
|
||||||
const onFileDrop = (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
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 (
|
|
||||||
<CardsWrapComponent
|
|
||||||
onFileDrop={onFileDrop}
|
|
||||||
dragMessage={"Drag your flow here"}
|
|
||||||
isLoading={isLoading && flows.length == 0}
|
|
||||||
>
|
|
||||||
{flows
|
|
||||||
.filter((flow) => !flow.is_component)
|
|
||||||
.reverse()
|
|
||||||
.map((flow, idx) => (
|
|
||||||
<CollectionCardComponent
|
|
||||||
key={idx}
|
|
||||||
data={flow}
|
|
||||||
button={
|
|
||||||
<Link to={"/flow/" + flow.id}>
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
size="sm"
|
|
||||||
className="whitespace-nowrap "
|
|
||||||
>
|
|
||||||
<IconComponent
|
|
||||||
name="ExternalLink"
|
|
||||||
className="main-page-nav-button"
|
|
||||||
/>
|
|
||||||
Edit Flow
|
|
||||||
</Button>
|
|
||||||
</Link>
|
|
||||||
}
|
|
||||||
onDelete={() => {
|
|
||||||
removeFlow(flow.id);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</CardsWrapComponent>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -2,10 +2,9 @@ import { useContext, useEffect } from "react";
|
||||||
import { Outlet, useNavigate } from "react-router-dom";
|
import { Outlet, useNavigate } from "react-router-dom";
|
||||||
import DropdownButton from "../../components/DropdownButtonComponent";
|
import DropdownButton from "../../components/DropdownButtonComponent";
|
||||||
import IconComponent from "../../components/genericIconComponent";
|
import IconComponent from "../../components/genericIconComponent";
|
||||||
import Header from "../../components/headerComponent";
|
import PageLayout from "../../components/pageLayout";
|
||||||
import SidebarNav from "../../components/sidebarComponent";
|
import SidebarNav from "../../components/sidebarComponent";
|
||||||
import { Button } from "../../components/ui/button";
|
import { Button } from "../../components/ui/button";
|
||||||
import { Separator } from "../../components/ui/separator";
|
|
||||||
import { USER_PROJECTS_HEADER } from "../../constants/constants";
|
import { USER_PROJECTS_HEADER } from "../../constants/constants";
|
||||||
import { alertContext } from "../../contexts/alertContext";
|
import { alertContext } from "../../contexts/alertContext";
|
||||||
import { FlowsContext } from "../../contexts/flowsContext";
|
import { FlowsContext } from "../../contexts/flowsContext";
|
||||||
|
|
@ -24,10 +23,18 @@ export default function HomePage(): JSX.Element {
|
||||||
const dropdownOptions = [
|
const dropdownOptions = [
|
||||||
{
|
{
|
||||||
name: "Import from JSON",
|
name: "Import from JSON",
|
||||||
onBtnClick: () =>
|
onBtnClick: () => {
|
||||||
uploadFlow(true).then((id) => {
|
try {
|
||||||
navigate("/flow/" + id);
|
uploadFlow(true).then((id) => {
|
||||||
}),
|
navigate("/flow/" + id);
|
||||||
|
});
|
||||||
|
} catch (error: any) {
|
||||||
|
setErrorData({
|
||||||
|
title: "Invalid file type",
|
||||||
|
list: [error],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const sidebarNavItems = [
|
const sidebarNavItems = [
|
||||||
|
|
@ -49,61 +56,49 @@ export default function HomePage(): JSX.Element {
|
||||||
|
|
||||||
// Personal flows display
|
// Personal flows display
|
||||||
return (
|
return (
|
||||||
<>
|
<PageLayout
|
||||||
<Header />
|
title={USER_PROJECTS_HEADER}
|
||||||
<div className="main-page-panel">
|
description="Manage your personal projects. Download or upload your collection."
|
||||||
<div className="main-page-nav-arrangement">
|
button={
|
||||||
<span className="main-page-nav-title">
|
<div className="flex gap-2">
|
||||||
<IconComponent name="Home" className="w-6" />
|
<Button
|
||||||
{USER_PROJECTS_HEADER}
|
variant="primary"
|
||||||
</span>
|
onClick={() => {
|
||||||
<div className="button-div-style">
|
downloadFlows();
|
||||||
<Button
|
}}
|
||||||
variant="primary"
|
>
|
||||||
onClick={() => {
|
<IconComponent name="Download" className="main-page-nav-button" />
|
||||||
downloadFlows();
|
Download Collection
|
||||||
}}
|
</Button>
|
||||||
>
|
<Button
|
||||||
<IconComponent name="Download" className="main-page-nav-button" />
|
variant="primary"
|
||||||
Download Collection
|
onClick={() => {
|
||||||
</Button>
|
uploadFlows();
|
||||||
<Button
|
}}
|
||||||
variant="primary"
|
>
|
||||||
onClick={() => {
|
<IconComponent name="Upload" className="main-page-nav-button" />
|
||||||
uploadFlows();
|
Upload Collection
|
||||||
}}
|
</Button>
|
||||||
>
|
<DropdownButton
|
||||||
<IconComponent name="Upload" className="main-page-nav-button" />
|
firstButtonName="New Project"
|
||||||
Upload Collection
|
onFirstBtnClick={() => {
|
||||||
</Button>
|
addFlow(true).then((id) => {
|
||||||
<DropdownButton
|
navigate("/flow/" + id);
|
||||||
firstButtonName="New Project"
|
});
|
||||||
onFirstBtnClick={() => {
|
}}
|
||||||
addFlow(true).then((id) => {
|
options={dropdownOptions}
|
||||||
navigate("/flow/" + id);
|
/>
|
||||||
});
|
|
||||||
}}
|
|
||||||
options={dropdownOptions}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<span className="main-page-description-text">
|
}
|
||||||
Manage your personal projects. Download or upload your collection.
|
>
|
||||||
</span>
|
<div className="flex h-full w-full space-y-8 lg:flex-row lg:space-x-8 lg:space-y-0">
|
||||||
<Separator className="my-6" />
|
<aside className="flex h-full flex-col space-y-6 lg:w-1/5">
|
||||||
<div className="flex flex-col space-y-8 lg:flex-row lg:space-x-8 lg:space-y-0">
|
<SidebarNav items={sidebarNavItems} />
|
||||||
<aside className="space-y-6 lg:w-1/5">
|
</aside>
|
||||||
{/* <Input placeholder="Search" onChange={(e) => {}} /> */}
|
<div className="h-full w-full flex-1">
|
||||||
<SidebarNav
|
<Outlet />
|
||||||
items={sidebarNavItems}
|
|
||||||
secondaryItems={sidebarNavItems}
|
|
||||||
/>
|
|
||||||
</aside>
|
|
||||||
<div className="w-full flex-1">
|
|
||||||
<Outlet />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</PageLayout>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ import ApiKeysPage from "./pages/ApiKeysPage";
|
||||||
import FlowPage from "./pages/FlowPage";
|
import FlowPage from "./pages/FlowPage";
|
||||||
import HomePage from "./pages/MainPage";
|
import HomePage from "./pages/MainPage";
|
||||||
import ComponentsComponent from "./pages/MainPage/components/components";
|
import ComponentsComponent from "./pages/MainPage/components/components";
|
||||||
import FlowsComponent from "./pages/MainPage/components/flows";
|
|
||||||
import ProfileSettingsPage from "./pages/ProfileSettingsPage";
|
import ProfileSettingsPage from "./pages/ProfileSettingsPage";
|
||||||
import StorePage from "./pages/StorePage";
|
import StorePage from "./pages/StorePage";
|
||||||
import ViewPage from "./pages/ViewPage";
|
import ViewPage from "./pages/ViewPage";
|
||||||
|
|
@ -37,8 +36,14 @@ const Router = () => {
|
||||||
</ProtectedRoute>
|
</ProtectedRoute>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Route path="flows" element={<FlowsComponent />} />
|
<Route
|
||||||
<Route path="components" element={<ComponentsComponent />} />
|
path="flows"
|
||||||
|
element={<ComponentsComponent key="flows" is_component={false} />}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path="components"
|
||||||
|
element={<ComponentsComponent key="components" />}
|
||||||
|
/>
|
||||||
</Route>
|
</Route>
|
||||||
<Route
|
<Route
|
||||||
path="/store"
|
path="/store"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue