Added components screen at My Collection

This commit is contained in:
Lucas Oliveira 2023-10-20 18:06:56 -03:00
commit bcfeaa6725
8 changed files with 355 additions and 77 deletions

View file

@ -12,7 +12,8 @@ import {
} from "../ui/card"; } from "../ui/card";
export const CardComponent = ({ export const CardComponent = ({
flow, isFlow,
data,
id, id,
onDelete, onDelete,
button, button,
@ -26,10 +27,10 @@ export const CardComponent = ({
<span <span
className={ className={
"card-component-image " + "card-component-image " +
gradients[parseInt(flow.id.slice(0, 12), 16) % gradients.length] gradients[parseInt(data.id.slice(0, 12), 16) % gradients.length]
} }
></span> ></span>
<span className="card-component-title-size">{flow.name}</span> <span className="card-component-title-size">{data.name}</span>
{onDelete && ( {onDelete && (
<button className="card-component-delete-button" onClick={onDelete}> <button className="card-component-delete-button" onClick={onDelete}>
<IconComponent <IconComponent
@ -41,18 +42,20 @@ export const CardComponent = ({
</CardTitle> </CardTitle>
<CardDescription className="card-component-desc"> <CardDescription className="card-component-desc">
<div className="card-component-desc-text"> <div className="card-component-desc-text">
{flow.description} {data.description}
{/* {flow.description} */} {/* {flow.description} */}
</div> </div>
</CardDescription> </CardDescription>
</CardHeader> </CardHeader>
<CardFooter> {isFlow && (
<div className="card-component-footer-arrangement"> <CardFooter>
<div className="card-component-footer"></div> <div className="card-component-footer-arrangement">
{button && button} <div className="card-component-footer"></div>
</div> {button && button}
</CardFooter> </div>
</CardFooter>
)}
</Card> </Card>
); );
}; };

View file

@ -0,0 +1,45 @@
import { Link, useLocation } from "react-router-dom";
import { cn } from "../../utils/utils";
import { buttonVariants } from "../ui/button";
interface SidebarNavProps extends React.HTMLAttributes<HTMLElement> {
items: {
href: string;
title: string;
}[];
}
export default function SidebarNav({
className,
items,
...props
}: SidebarNavProps) {
const location = useLocation();
const pathname = location.pathname;
return (
<nav
className={cn(
"flex space-x-2 lg:flex-col lg:space-x-0 lg:space-y-1",
className
)}
{...props}
>
{items.map((item) => (
<Link
key={item.href}
to={item.href}
className={cn(
buttonVariants({ variant: "ghost" }),
pathname === item.href
? "bg-background hover:bg-background"
: "hover:bg-transparent hover:underline",
"justify-start"
)}
>
{item.title}
</Link>
))}
</nav>
);
}

View file

@ -0,0 +1,132 @@
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 ComponentsComponent() {
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 (
<div
onDragOver={dragOver}
onDragEnter={dragEnter}
onDragLeave={dragLeave}
onDrop={fileDrop}
className={
"h-full w-full " +
(isDragging
? "mb-24 flex flex-col items-center justify-center gap-4 text-2xl font-light"
: "")
}
>
{isDragging ? (
<>
<IconComponent name="ArrowUpToLine" className="h-12 w-12 stroke-1" />
Drop your flow here
</>
) : (
<div className="main-page-flows-display">
{isLoading && flows.length == 0 ? (
<>
<SkeletonCardComponent />
<SkeletonCardComponent />
<SkeletonCardComponent />
<SkeletonCardComponent />
</>
) : (
flows
.filter((flow) => !flow.is_component)
.map((flow, idx) => (
<CardComponent
key={idx}
data={flow}
id={flow.id}
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);
}}
/>
))
)}
</div>
)}
</div>
);
}

View file

@ -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 (
<div
onDragOver={dragOver}
onDragEnter={dragEnter}
onDragLeave={dragLeave}
onDrop={fileDrop}
className={
"h-full w-full " +
(isDragging
? "mb-24 flex flex-col items-center justify-center gap-4 text-2xl font-light"
: "")
}
>
{isDragging ? (
<>
<IconComponent name="ArrowUpToLine" className="h-12 w-12 stroke-1" />
Drop your flow here
</>
) : (
<div className="main-page-flows-display">
{isLoading && flows.length == 0 ? (
<>
<SkeletonCardComponent />
<SkeletonCardComponent />
<SkeletonCardComponent />
<SkeletonCardComponent />
</>
) : (
flows
.filter((flow) => !flow.is_component)
.map((flow, idx) => (
<CardComponent
key={idx}
isFlow
data={flow}
id={flow.id}
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);
}}
/>
))
)}
</div>
)}
</div>
);
}

View file

@ -1,11 +1,11 @@
import { useContext, useEffect, useState } from "react"; 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 DropdownButton from "../../components/DropdownButtonComponent";
import { CardComponent } from "../../components/cardComponent";
import IconComponent from "../../components/genericIconComponent"; import IconComponent from "../../components/genericIconComponent";
import Header from "../../components/headerComponent"; import Header from "../../components/headerComponent";
import { SkeletonCardComponent } from "../../components/skeletonCardComponent"; 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 { TabsContext } from "../../contexts/tabsContext"; 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 // Set a null id
useEffect(() => { useEffect(() => {
@ -115,66 +125,15 @@ export default function HomePage(): JSX.Element {
<span className="main-page-description-text"> <span className="main-page-description-text">
Manage your personal projects. Download or upload your collection. Manage your personal projects. Download or upload your collection.
</span> </span>
<div <Separator className="my-6" />
onDragOver={dragOver} <div className="flex flex-col space-y-8 lg:flex-row lg:space-x-8 lg:space-y-0">
onDragEnter={dragEnter} <aside className="space-y-6 lg:w-1/5">
onDragLeave={dragLeave} {/* <Input placeholder="Search" onChange={(e) => {}} /> */}
onDrop={fileDrop} <SidebarNav items={sidebarNavItems} />
className={ </aside>
"h-full w-full " + <div className="w-full flex-1">
(isDragging <Outlet />
? "mb-24 flex flex-col items-center justify-center gap-4 text-2xl font-light" </div>
: "")
}
>
{isDragging ? (
<>
<IconComponent
name="ArrowUpToLine"
className="h-12 w-12 stroke-1"
/>
Drop your flow here
</>
) : (
<div className="main-page-flows-display">
{isLoading && flows.length == 0 ? (
<>
<SkeletonCardComponent />
<SkeletonCardComponent />
<SkeletonCardComponent />
<SkeletonCardComponent />
</>
) : (
flows
.filter((flow) => !flow.is_component)
.map((flow, idx) => (
<CardComponent
key={idx}
flow={flow}
id={flow.id}
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);
}}
/>
))
)}
</div>
)}
</div> </div>
</div> </div>
</> </>

View file

@ -9,6 +9,8 @@ import ApiKeysPage from "./pages/ApiKeysPage";
import CommunityPage from "./pages/CommunityPage"; import CommunityPage from "./pages/CommunityPage";
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 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";
@ -26,7 +28,10 @@ const Router = () => {
<HomePage /> <HomePage />
</ProtectedRoute> </ProtectedRoute>
} }
/> >
<Route path="flows" element={<FlowsComponent />} />
<Route path="components" element={<ComponentsComponent />} />
</Route>
<Route <Route
path="/community" path="/community"
element={ element={

View file

@ -229,7 +229,7 @@
} }
.main-page-description-text { .main-page-description-text {
@apply flex w-[60%] px-6 pb-14 text-muted-foreground; @apply flex w-[60%] px-6 pb-4 text-muted-foreground;
} }
.admin-page-description-text { .admin-page-description-text {
@ -237,7 +237,7 @@
} }
.main-page-flows-display { .main-page-flows-display {
@apply grid w-full gap-4 p-4 md:grid-cols-2 lg:grid-cols-4; @apply grid w-full gap-4 md:grid-cols-2 lg:grid-cols-4;
} }
.community-page-arrangement { .community-page-arrangement {

View file

@ -531,7 +531,8 @@ export type groupDataType = {
}; };
export type cardComponentPropsType = { export type cardComponentPropsType = {
flow: FlowType; isFlow?: boolean;
data: FlowType;
id: string; id: string;
onDelete?: () => void; onDelete?: () => void;
button?: JSX.Element; button?: JSX.Element;