Sync with Langflow Store

This commit is contained in:
Lucas Oliveira 2023-11-18 18:06:33 -03:00
commit a81abb4c2d
4 changed files with 353 additions and 250 deletions

View file

@ -3,6 +3,7 @@ import { alertContext } from "../../contexts/alertContext";
import { FlowsContext } from "../../contexts/flowsContext"; import { FlowsContext } from "../../contexts/flowsContext";
import { StoreContext } from "../../contexts/storeContext"; import { StoreContext } from "../../contexts/storeContext";
import { getComponent, postLikeComponent } from "../../controllers/API"; import { getComponent, postLikeComponent } from "../../controllers/API";
import DeleteConfirmationModal from "../../modals/DeleteConfirmationModal";
import { storeComponent } from "../../types/store"; import { storeComponent } from "../../types/store";
import cloneFLowWithParent from "../../utils/storeUtils"; import cloneFLowWithParent from "../../utils/storeUtils";
import { cn } from "../../utils/utils"; import { cn } from "../../utils/utils";
@ -166,13 +167,17 @@ export default function CollectionCardComponent({
</div> </div>
)} )}
{onDelete && ( {onDelete && !data.metadata && (
<button onClick={onDelete}> <DeleteConfirmationModal
onConfirm={() => {
onDelete();
}}
>
<IconComponent <IconComponent
name="Trash2" name="Trash2"
className="h-5 w-5 text-primary opacity-0 transition-all hover:text-destructive group-hover:opacity-100" className="h-5 w-5 text-primary opacity-0 transition-all hover:text-destructive group-hover:opacity-100"
/> />
</button> </DeleteConfirmationModal>
)} )}
</CardTitle> </CardTitle>
</div> </div>
@ -207,8 +212,40 @@ export default function CollectionCardComponent({
</div> </div>
{data.liked_by_count != undefined && ( {data.liked_by_count != undefined && (
<div className="flex gap-0.5"> <div className="flex gap-0.5">
{onDelete && data.metadata ? (
<ShadTooltip <ShadTooltip
content={authorized ? "Like" : "Please review your API key."} content={
authorized ? "Delete" : "Please review your API key."
}
>
<DeleteConfirmationModal
onConfirm={() => {
onDelete();
}}
>
<Button
variant="ghost"
size="xs"
className={
"whitespace-nowrap" +
(!authorized ? " cursor-not-allowed" : "")
}
>
<IconComponent
name="Trash2"
className={cn(
"h-5 w-5",
!authorized ? " text-ring" : ""
)}
/>
</Button>
</DeleteConfirmationModal>
</ShadTooltip>
) : (
<ShadTooltip
content={
authorized ? "Like" : "Please review your API key."
}
> >
<Button <Button
disabled={loadingLike} disabled={loadingLike}
@ -237,6 +274,7 @@ export default function CollectionCardComponent({
/> />
</Button> </Button>
</ShadTooltip> </ShadTooltip>
)}
<ShadTooltip <ShadTooltip
content={ content={
authorized authorized

View file

@ -0,0 +1,26 @@
import Header from "../headerComponent";
import { Separator } from "../ui/separator";
export default function PageLayout({
title,
description,
children,
}: {
title: string;
description: string;
children: React.ReactNode;
}) {
return (
<div className="flex h-screen w-full flex-col">
<Header />
<div className="flex h-full w-full flex-col justify-between overflow-auto bg-background px-16">
<div className="flex w-full flex-col justify-between space-y-0.5 py-8 pb-2">
<h2 className="text-2xl font-bold tracking-tight">{title}</h2>
<p className="text-muted-foreground">{description}</p>
</div>
<Separator className="my-6 flex" />
{children}
</div>
</div>
);
}

View file

@ -0,0 +1,56 @@
import { DialogClose } from "@radix-ui/react-dialog";
import { Trash2 } from "lucide-react";
import { Button } from "../../components/ui/button";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "../../components/ui/dialog";
export default function DeleteConfirmationModal({
children,
onConfirm,
description,
}: {
children: JSX.Element;
onConfirm: () => void;
description?: string;
}) {
return (
<Dialog>
<DialogTrigger>{children}</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>
<div className="flex">
Delete <Trash2 className="ml-3 h-4 w-4" strokeWidth={1.5} />
</div>
</DialogTitle>
<DialogDescription>
Are you sure you want to delete this {description ?? "component"}?
<br></br>
This action cannot be undone.
</DialogDescription>
</DialogHeader>
<DialogFooter>
<DialogClose>
<Button className="mr-3">Cancel</Button>
<Button
type="submit"
onClick={() => {
onConfirm();
}}
>
Delete
</Button>
</DialogClose>
</DialogFooter>
</DialogContent>
</Dialog>
);
}

View file

@ -4,10 +4,9 @@ import PaginatorComponent from "../../components/PaginatorComponent";
import ShadTooltip from "../../components/ShadTooltipComponent"; import ShadTooltip from "../../components/ShadTooltipComponent";
import CollectionCardComponent from "../../components/cardComponent"; import CollectionCardComponent from "../../components/cardComponent";
import IconComponent from "../../components/genericIconComponent"; import IconComponent from "../../components/genericIconComponent";
import Header from "../../components/headerComponent"; import PageLayout from "../../components/pageLayout";
import { SkeletonCardComponent } from "../../components/skeletonCardComponent"; import { SkeletonCardComponent } from "../../components/skeletonCardComponent";
import { Badge } from "../../components/ui/badge"; import { Badge } from "../../components/ui/badge";
import { Button } from "../../components/ui/button";
import { Input } from "../../components/ui/input"; import { Input } from "../../components/ui/input";
import { import {
Select, Select,
@ -21,7 +20,6 @@ import { alertContext } from "../../contexts/alertContext";
import { AuthContext } from "../../contexts/authContext"; import { AuthContext } from "../../contexts/authContext";
import { StoreContext } from "../../contexts/storeContext"; import { StoreContext } from "../../contexts/storeContext";
import { getStoreComponents, getStoreTags } from "../../controllers/API"; import { getStoreComponents, getStoreTags } from "../../controllers/API";
import StoreApiKeyModal from "../../modals/StoreApiKeyModal";
import { storeComponent } from "../../types/store"; import { storeComponent } from "../../types/store";
import { cn } from "../../utils/utils"; import { cn } from "../../utils/utils";
export default function StorePage(): JSX.Element { export default function StorePage(): JSX.Element {
@ -197,18 +195,10 @@ export default function StorePage(): JSX.Element {
}; };
return ( return (
<> <PageLayout
<Header /> title="Langflow Store"
description="Search flows and components from the community."
<div className="flex h-full w-full flex-col justify-between overflow-auto bg-background px-16"> /* button={{StoreApiKeyModal && (
<div>
<div className="flex w-full justify-between py-8 pb-2">
<span className="flex items-center justify-center gap-2 text-2xl font-semibold">
<IconComponent name="Store" className="w-6" />
Langflow Store
</span>
<div className="flex gap-2">
{StoreApiKeyModal && (
<StoreApiKeyModal disabled={loading}> <StoreApiKeyModal disabled={loading}>
<Button <Button
disabled={loading} disabled={loading}
@ -222,12 +212,9 @@ export default function StorePage(): JSX.Element {
API Key API Key
</Button> </Button>
</StoreApiKeyModal> </StoreApiKeyModal>
)} )}} */
</div> >
</div> <div className="flex h-full w-full flex-col justify-between">
<span className="flex w-[70%] pb-8 text-muted-foreground">
Search flows and components from the community.
</span>
<div className="flex w-full flex-col gap-4 p-0"> <div className="flex w-full flex-col gap-4 p-0">
<div className="flex items-end gap-4"> <div className="flex items-end gap-4">
<div className="relative h-12 w-[40%]"> <div className="relative h-12 w-[40%]">
@ -254,9 +241,7 @@ export default function StorePage(): JSX.Element {
> >
<IconComponent <IconComponent
name={loading ? "Loader2" : "Search"} name={loading ? "Loader2" : "Search"}
className={ className={loading ? " animate-spin cursor-not-allowed" : ""}
loading ? " animate-spin cursor-not-allowed" : ""
}
/> />
</button> </button>
</div> </div>
@ -365,8 +350,7 @@ export default function StorePage(): JSX.Element {
<span className="px-0.5 text-sm text-muted-foreground"> <span className="px-0.5 text-sm text-muted-foreground">
{(!loading || searchData.length !== 0) && ( {(!loading || searchData.length !== 0) && (
<> <>
{totalRowsCount}{" "} {totalRowsCount} {totalRowsCount !== 1 ? "results" : "result"}
{totalRowsCount !== 1 ? "results" : "result"}
</> </>
)} )}
</span> </span>
@ -425,9 +409,8 @@ export default function StorePage(): JSX.Element {
</div> </div>
)} )}
</div> </div>
</div>
{!loading && searchData.length > 0 && ( {!loading && searchData.length > 0 && (
<div className="relative my-6"> <div className="relative py-6">
<PaginatorComponent <PaginatorComponent
storeComponent={true} storeComponent={true}
pageIndex={pageIndex} pageIndex={pageIndex}
@ -441,6 +424,6 @@ export default function StorePage(): JSX.Element {
</div> </div>
)} )}
</div> </div>
</> </PageLayout>
); );
} }