Sync with Langflow Store
This commit is contained in:
parent
d009476a8e
commit
a81abb4c2d
4 changed files with 353 additions and 250 deletions
|
|
@ -3,6 +3,7 @@ import { alertContext } from "../../contexts/alertContext";
|
|||
import { FlowsContext } from "../../contexts/flowsContext";
|
||||
import { StoreContext } from "../../contexts/storeContext";
|
||||
import { getComponent, postLikeComponent } from "../../controllers/API";
|
||||
import DeleteConfirmationModal from "../../modals/DeleteConfirmationModal";
|
||||
import { storeComponent } from "../../types/store";
|
||||
import cloneFLowWithParent from "../../utils/storeUtils";
|
||||
import { cn } from "../../utils/utils";
|
||||
|
|
@ -166,13 +167,17 @@ export default function CollectionCardComponent({
|
|||
</div>
|
||||
)}
|
||||
|
||||
{onDelete && (
|
||||
<button onClick={onDelete}>
|
||||
{onDelete && !data.metadata && (
|
||||
<DeleteConfirmationModal
|
||||
onConfirm={() => {
|
||||
onDelete();
|
||||
}}
|
||||
>
|
||||
<IconComponent
|
||||
name="Trash2"
|
||||
className="h-5 w-5 text-primary opacity-0 transition-all hover:text-destructive group-hover:opacity-100"
|
||||
/>
|
||||
</button>
|
||||
</DeleteConfirmationModal>
|
||||
)}
|
||||
</CardTitle>
|
||||
</div>
|
||||
|
|
@ -207,36 +212,69 @@ export default function CollectionCardComponent({
|
|||
</div>
|
||||
{data.liked_by_count != undefined && (
|
||||
<div className="flex gap-0.5">
|
||||
<ShadTooltip
|
||||
content={authorized ? "Like" : "Please review your API key."}
|
||||
>
|
||||
<Button
|
||||
disabled={loadingLike}
|
||||
variant="ghost"
|
||||
size="xs"
|
||||
className={
|
||||
"whitespace-nowrap" +
|
||||
(!authorized ? " cursor-not-allowed" : "")
|
||||
{onDelete && data.metadata ? (
|
||||
<ShadTooltip
|
||||
content={
|
||||
authorized ? "Delete" : "Please review your API key."
|
||||
}
|
||||
onClick={() => {
|
||||
if (!authorized) {
|
||||
return;
|
||||
}
|
||||
handleLike();
|
||||
}}
|
||||
>
|
||||
<IconComponent
|
||||
name="Heart"
|
||||
className={cn(
|
||||
"h-5 w-5",
|
||||
liked_by_user
|
||||
? "fill-destructive stroke-destructive"
|
||||
: "",
|
||||
!authorized ? " text-ring" : ""
|
||||
)}
|
||||
/>
|
||||
</Button>
|
||||
</ShadTooltip>
|
||||
<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
|
||||
disabled={loadingLike}
|
||||
variant="ghost"
|
||||
size="xs"
|
||||
className={
|
||||
"whitespace-nowrap" +
|
||||
(!authorized ? " cursor-not-allowed" : "")
|
||||
}
|
||||
onClick={() => {
|
||||
if (!authorized) {
|
||||
return;
|
||||
}
|
||||
handleLike();
|
||||
}}
|
||||
>
|
||||
<IconComponent
|
||||
name="Heart"
|
||||
className={cn(
|
||||
"h-5 w-5",
|
||||
liked_by_user
|
||||
? "fill-destructive stroke-destructive"
|
||||
: "",
|
||||
!authorized ? " text-ring" : ""
|
||||
)}
|
||||
/>
|
||||
</Button>
|
||||
</ShadTooltip>
|
||||
)}
|
||||
<ShadTooltip
|
||||
content={
|
||||
authorized
|
||||
|
|
|
|||
26
src/frontend/src/components/pageLayout/index.tsx
Normal file
26
src/frontend/src/components/pageLayout/index.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
56
src/frontend/src/modals/DeleteConfirmationModal/index.tsx
Normal file
56
src/frontend/src/modals/DeleteConfirmationModal/index.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
|
|
@ -4,10 +4,9 @@ import PaginatorComponent from "../../components/PaginatorComponent";
|
|||
import ShadTooltip from "../../components/ShadTooltipComponent";
|
||||
import CollectionCardComponent from "../../components/cardComponent";
|
||||
import IconComponent from "../../components/genericIconComponent";
|
||||
import Header from "../../components/headerComponent";
|
||||
import PageLayout from "../../components/pageLayout";
|
||||
import { SkeletonCardComponent } from "../../components/skeletonCardComponent";
|
||||
import { Badge } from "../../components/ui/badge";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import { Input } from "../../components/ui/input";
|
||||
import {
|
||||
Select,
|
||||
|
|
@ -21,7 +20,6 @@ import { alertContext } from "../../contexts/alertContext";
|
|||
import { AuthContext } from "../../contexts/authContext";
|
||||
import { StoreContext } from "../../contexts/storeContext";
|
||||
import { getStoreComponents, getStoreTags } from "../../controllers/API";
|
||||
import StoreApiKeyModal from "../../modals/StoreApiKeyModal";
|
||||
import { storeComponent } from "../../types/store";
|
||||
import { cn } from "../../utils/utils";
|
||||
export default function StorePage(): JSX.Element {
|
||||
|
|
@ -197,237 +195,222 @@ export default function StorePage(): JSX.Element {
|
|||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Header />
|
||||
|
||||
<div className="flex h-full w-full flex-col justify-between overflow-auto bg-background px-16">
|
||||
<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}>
|
||||
<Button
|
||||
disabled={loading}
|
||||
className={cn(
|
||||
`${!validApiKey ? "animate-pulse border-error" : ""}`,
|
||||
loading ? "cursor-not-allowed" : ""
|
||||
)}
|
||||
variant="primary"
|
||||
>
|
||||
<IconComponent name="Key" className="mr-2 w-4" />
|
||||
API Key
|
||||
</Button>
|
||||
</StoreApiKeyModal>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<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 items-end gap-4">
|
||||
<div className="relative h-12 w-[40%]">
|
||||
<Input
|
||||
disabled={loading}
|
||||
placeholder="Search Flows and Components"
|
||||
className="absolute h-12 pl-5 pr-12"
|
||||
onChange={(e) => {
|
||||
setInputText(e.target.value);
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Enter") {
|
||||
setSearchNow(uniqueId());
|
||||
}
|
||||
}}
|
||||
value={inputText}
|
||||
/>
|
||||
<button
|
||||
disabled={loading}
|
||||
className="absolute bottom-0 right-4 top-0 my-auto h-6 cursor-pointer stroke-1 text-muted-foreground"
|
||||
onClick={() => {
|
||||
<PageLayout
|
||||
title="Langflow Store"
|
||||
description="Search flows and components from the community."
|
||||
/* button={{StoreApiKeyModal && (
|
||||
<StoreApiKeyModal disabled={loading}>
|
||||
<Button
|
||||
disabled={loading}
|
||||
className={cn(
|
||||
`${!validApiKey ? "animate-pulse border-error" : ""}`,
|
||||
loading ? "cursor-not-allowed" : ""
|
||||
)}
|
||||
variant="primary"
|
||||
>
|
||||
<IconComponent name="Key" className="mr-2 w-4" />
|
||||
API Key
|
||||
</Button>
|
||||
</StoreApiKeyModal>
|
||||
)}} */
|
||||
>
|
||||
<div className="flex h-full w-full flex-col justify-between">
|
||||
<div className="flex w-full flex-col gap-4 p-0">
|
||||
<div className="flex items-end gap-4">
|
||||
<div className="relative h-12 w-[40%]">
|
||||
<Input
|
||||
disabled={loading}
|
||||
placeholder="Search Flows and Components"
|
||||
className="absolute h-12 pl-5 pr-12"
|
||||
onChange={(e) => {
|
||||
setInputText(e.target.value);
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Enter") {
|
||||
setSearchNow(uniqueId());
|
||||
}}
|
||||
>
|
||||
<IconComponent
|
||||
name={loading ? "Loader2" : "Search"}
|
||||
className={
|
||||
loading ? " animate-spin cursor-not-allowed" : ""
|
||||
}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<div className="ml-4 flex w-full gap-2 border-b border-border">
|
||||
<button
|
||||
disabled={loading}
|
||||
onClick={() => {
|
||||
setTabActive("All");
|
||||
}}
|
||||
className={
|
||||
(tabActive === "All"
|
||||
? "border-b-2 border-primary p-3"
|
||||
: " border-b-2 border-transparent p-3 text-muted-foreground hover:text-primary") +
|
||||
(loading ? " cursor-not-allowed " : "")
|
||||
}
|
||||
>
|
||||
All
|
||||
</button>
|
||||
<button
|
||||
disabled={loading}
|
||||
onClick={() => {
|
||||
setTabActive("Flows");
|
||||
}}
|
||||
className={
|
||||
(tabActive === "Flows"
|
||||
? "border-b-2 border-primary p-3"
|
||||
: " border-b-2 border-transparent p-3 text-muted-foreground hover:text-primary") +
|
||||
(loading ? " cursor-not-allowed " : "")
|
||||
}
|
||||
>
|
||||
Flows
|
||||
</button>
|
||||
<button
|
||||
disabled={loading}
|
||||
onClick={() => {
|
||||
setTabActive("Components");
|
||||
}}
|
||||
className={
|
||||
(tabActive === "Components"
|
||||
? "border-b-2 border-primary p-3"
|
||||
: " border-b-2 border-transparent p-3 text-muted-foreground hover:text-primary") +
|
||||
(loading ? " cursor-not-allowed " : "")
|
||||
}
|
||||
>
|
||||
Components
|
||||
</button>
|
||||
<ShadTooltip content="Coming Soon">
|
||||
<button className="cursor-not-allowed p-3 text-muted-foreground">
|
||||
Bundles
|
||||
</button>
|
||||
</ShadTooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<Select
|
||||
}}
|
||||
value={inputText}
|
||||
/>
|
||||
<button
|
||||
disabled={loading}
|
||||
onValueChange={setSelectFilter}
|
||||
value={selectFilter}
|
||||
>
|
||||
<SelectTrigger className="mr-4 w-[160px] flex-shrink-0">
|
||||
<SelectValue placeholder="Filter Values" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectItem value="all">All</SelectItem>
|
||||
<SelectItem value="createdbyme">Created By Me</SelectItem>
|
||||
<SelectItem value="likedbyme">Liked By Me</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<div ref={fadeContainerRef} className="fade-container">
|
||||
<div
|
||||
ref={scrollContainerRef}
|
||||
className="scroll-container flex gap-2"
|
||||
>
|
||||
{!loadingTags &&
|
||||
tags.map((tag, idx) => (
|
||||
<button
|
||||
disabled={loading}
|
||||
className={loading ? "cursor-not-allowed" : ""}
|
||||
onClick={() => {
|
||||
updateTags(tag.name);
|
||||
}}
|
||||
>
|
||||
<Badge
|
||||
key={idx}
|
||||
variant="outline"
|
||||
size="sq"
|
||||
className={cn(
|
||||
filteredCategories.some(
|
||||
(category) => category === tag.name
|
||||
)
|
||||
? "bg-beta-foreground text-background hover:bg-beta-foreground"
|
||||
: ""
|
||||
)}
|
||||
>
|
||||
{tag.name}
|
||||
</Badge>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-end justify-between">
|
||||
<span className="px-0.5 text-sm text-muted-foreground">
|
||||
{(!loading || searchData.length !== 0) && (
|
||||
<>
|
||||
{totalRowsCount}{" "}
|
||||
{totalRowsCount !== 1 ? "results" : "result"}
|
||||
</>
|
||||
)}
|
||||
</span>
|
||||
|
||||
<Select
|
||||
disabled={loading}
|
||||
onValueChange={(e) => {
|
||||
setPageOrder(e);
|
||||
className="absolute bottom-0 right-4 top-0 my-auto h-6 cursor-pointer stroke-1 text-muted-foreground"
|
||||
onClick={() => {
|
||||
setSearchNow(uniqueId());
|
||||
}}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Popular" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="Popular">Popular</SelectItem>
|
||||
{/* <SelectItem value="Recent">Most Recent</SelectItem> */}
|
||||
<SelectItem value="Alphabetical">Alphabetical</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<IconComponent
|
||||
name={loading ? "Loader2" : "Search"}
|
||||
className={loading ? " animate-spin cursor-not-allowed" : ""}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<div className="ml-4 flex w-full gap-2 border-b border-border">
|
||||
<button
|
||||
disabled={loading}
|
||||
onClick={() => {
|
||||
setTabActive("All");
|
||||
}}
|
||||
className={
|
||||
(tabActive === "All"
|
||||
? "border-b-2 border-primary p-3"
|
||||
: " border-b-2 border-transparent p-3 text-muted-foreground hover:text-primary") +
|
||||
(loading ? " cursor-not-allowed " : "")
|
||||
}
|
||||
>
|
||||
All
|
||||
</button>
|
||||
<button
|
||||
disabled={loading}
|
||||
onClick={() => {
|
||||
setTabActive("Flows");
|
||||
}}
|
||||
className={
|
||||
(tabActive === "Flows"
|
||||
? "border-b-2 border-primary p-3"
|
||||
: " border-b-2 border-transparent p-3 text-muted-foreground hover:text-primary") +
|
||||
(loading ? " cursor-not-allowed " : "")
|
||||
}
|
||||
>
|
||||
Flows
|
||||
</button>
|
||||
<button
|
||||
disabled={loading}
|
||||
onClick={() => {
|
||||
setTabActive("Components");
|
||||
}}
|
||||
className={
|
||||
(tabActive === "Components"
|
||||
? "border-b-2 border-primary p-3"
|
||||
: " border-b-2 border-transparent p-3 text-muted-foreground hover:text-primary") +
|
||||
(loading ? " cursor-not-allowed " : "")
|
||||
}
|
||||
>
|
||||
Components
|
||||
</button>
|
||||
<ShadTooltip content="Coming Soon">
|
||||
<button className="cursor-not-allowed p-3 text-muted-foreground">
|
||||
Bundles
|
||||
</button>
|
||||
</ShadTooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid w-full gap-4 md:grid-cols-2 lg:grid-cols-3">
|
||||
{!loading || searchData.length !== 0 ? (
|
||||
searchData.map((item) => {
|
||||
return (
|
||||
<>
|
||||
<CollectionCardComponent
|
||||
key={item.id}
|
||||
data={item}
|
||||
authorized={validApiKey}
|
||||
disabled={loading}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
})
|
||||
) : (
|
||||
<div className="flex items-center gap-2">
|
||||
<Select
|
||||
disabled={loading}
|
||||
onValueChange={setSelectFilter}
|
||||
value={selectFilter}
|
||||
>
|
||||
<SelectTrigger className="mr-4 w-[160px] flex-shrink-0">
|
||||
<SelectValue placeholder="Filter Values" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectItem value="all">All</SelectItem>
|
||||
<SelectItem value="createdbyme">Created By Me</SelectItem>
|
||||
<SelectItem value="likedbyme">Liked By Me</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<div ref={fadeContainerRef} className="fade-container">
|
||||
<div
|
||||
ref={scrollContainerRef}
|
||||
className="scroll-container flex gap-2"
|
||||
>
|
||||
{!loadingTags &&
|
||||
tags.map((tag, idx) => (
|
||||
<button
|
||||
disabled={loading}
|
||||
className={loading ? "cursor-not-allowed" : ""}
|
||||
onClick={() => {
|
||||
updateTags(tag.name);
|
||||
}}
|
||||
>
|
||||
<Badge
|
||||
key={idx}
|
||||
variant="outline"
|
||||
size="sq"
|
||||
className={cn(
|
||||
filteredCategories.some(
|
||||
(category) => category === tag.name
|
||||
)
|
||||
? "bg-beta-foreground text-background hover:bg-beta-foreground"
|
||||
: ""
|
||||
)}
|
||||
>
|
||||
{tag.name}
|
||||
</Badge>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-end justify-between">
|
||||
<span className="px-0.5 text-sm text-muted-foreground">
|
||||
{(!loading || searchData.length !== 0) && (
|
||||
<>
|
||||
<SkeletonCardComponent />
|
||||
<SkeletonCardComponent />
|
||||
<SkeletonCardComponent />
|
||||
{totalRowsCount} {totalRowsCount !== 1 ? "results" : "result"}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</span>
|
||||
|
||||
{!loading && searchData?.length === 0 && (
|
||||
<div className="mt-6 flex w-full items-center justify-center text-center">
|
||||
<div className="flex h-full w-full flex-col">
|
||||
<div className="flex w-full flex-col gap-4">
|
||||
<div className="grid w-full gap-4">
|
||||
You haven't{" "}
|
||||
{selectFilter === "createdbyme" ? "created" : "liked"}{" "}
|
||||
anything yet.
|
||||
</div>
|
||||
<Select
|
||||
disabled={loading}
|
||||
onValueChange={(e) => {
|
||||
setPageOrder(e);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Popular" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="Popular">Popular</SelectItem>
|
||||
{/* <SelectItem value="Recent">Most Recent</SelectItem> */}
|
||||
<SelectItem value="Alphabetical">Alphabetical</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div className="grid w-full gap-4 md:grid-cols-2 lg:grid-cols-3">
|
||||
{!loading || searchData.length !== 0 ? (
|
||||
searchData.map((item) => {
|
||||
return (
|
||||
<>
|
||||
<CollectionCardComponent
|
||||
key={item.id}
|
||||
data={item}
|
||||
authorized={validApiKey}
|
||||
disabled={loading}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
})
|
||||
) : (
|
||||
<>
|
||||
<SkeletonCardComponent />
|
||||
<SkeletonCardComponent />
|
||||
<SkeletonCardComponent />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{!loading && searchData?.length === 0 && (
|
||||
<div className="mt-6 flex w-full items-center justify-center text-center">
|
||||
<div className="flex h-full w-full flex-col">
|
||||
<div className="flex w-full flex-col gap-4">
|
||||
<div className="grid w-full gap-4">
|
||||
You haven't{" "}
|
||||
{selectFilter === "createdbyme" ? "created" : "liked"}{" "}
|
||||
anything yet.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{!loading && searchData.length > 0 && (
|
||||
<div className="relative my-6">
|
||||
<div className="relative py-6">
|
||||
<PaginatorComponent
|
||||
storeComponent={true}
|
||||
pageIndex={pageIndex}
|
||||
|
|
@ -441,6 +424,6 @@ export default function StorePage(): JSX.Element {
|
|||
</div>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
</PageLayout>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue