mirror of
https://github.com/community-scripts/ProxmoxVE
synced 2025-02-12 02:39:17 +00:00
Add most popular scripts feature and update script rendering logic in ScriptInfoBlocks
component
This commit is contained in:
parent
36b0691ad9
commit
974b31bfb3
@ -7,8 +7,9 @@ import {
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
import { mostPopularScripts } from "@/config/siteConfig";
|
||||
import { extractDate } from "@/lib/time";
|
||||
import { Category } from "@/lib/types";
|
||||
import { Category, Script } from "@/lib/types";
|
||||
import { CalendarPlus } from "lucide-react";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
@ -16,6 +17,19 @@ import { useMemo, useState } from "react";
|
||||
|
||||
const ITEMS_PER_PAGE = 3;
|
||||
|
||||
export const getCorrectTypeNaming = (type: string) => {
|
||||
switch (type) {
|
||||
case "ct":
|
||||
return "LXC";
|
||||
case "vm":
|
||||
return "VM";
|
||||
case "misc":
|
||||
return "";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
export function LatestScripts({ items }: { items: Category[] }) {
|
||||
const [page, setPage] = useState(1);
|
||||
|
||||
@ -23,7 +37,8 @@ export function LatestScripts({ items }: { items: Category[] }) {
|
||||
if (!items) return [];
|
||||
const scripts = items.flatMap((category) => category.scripts || []);
|
||||
return scripts.sort(
|
||||
(a, b) => new Date(b.date_created).getTime() - new Date(a.date_created).getTime(),
|
||||
(a, b) =>
|
||||
new Date(b.date_created).getTime() - new Date(a.date_created).getTime(),
|
||||
);
|
||||
}, [items]);
|
||||
|
||||
@ -68,16 +83,16 @@ export function LatestScripts({ items }: { items: Category[] }) {
|
||||
</div>
|
||||
)}
|
||||
<div className="min-w flex w-full flex-row flex-wrap gap-4">
|
||||
{latestScripts.slice(startIndex, endIndex).map((item) => (
|
||||
{latestScripts.slice(startIndex, endIndex).map((script) => (
|
||||
<Card
|
||||
key={item.name}
|
||||
key={script.name}
|
||||
className="min-w-[250px] flex-1 flex-grow bg-accent/30"
|
||||
>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-3">
|
||||
<div className="flex h-16 w-16 items-center justify-center rounded-lg bg-accent p-1">
|
||||
<Image
|
||||
src={item.logo || "/logo.png"}
|
||||
src={script.logo || "/logo.png"}
|
||||
unoptimized
|
||||
height={64}
|
||||
width={64}
|
||||
@ -87,18 +102,18 @@ export function LatestScripts({ items }: { items: Category[] }) {
|
||||
</div>
|
||||
<div className="flex flex-col">
|
||||
<p className="text-lg line-clamp-1">
|
||||
{item.name} {item.type}
|
||||
{script.name} {getCorrectTypeNaming(script.type)}
|
||||
</p>
|
||||
<p className="text-sm text-muted-foreground flex items-center gap-1">
|
||||
<CalendarPlus className="h-4 w-4" />
|
||||
{extractDate(item.date_created)}
|
||||
{extractDate(script.date_created)}
|
||||
</p>
|
||||
</div>
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<CardDescription className="line-clamp-3 text-card-foreground">
|
||||
{item.description}
|
||||
{script.description}
|
||||
</CardDescription>
|
||||
</CardContent>
|
||||
<CardFooter className="">
|
||||
@ -106,7 +121,7 @@ export function LatestScripts({ items }: { items: Category[] }) {
|
||||
<Link
|
||||
href={{
|
||||
pathname: "/scripts",
|
||||
query: { id: item.name },
|
||||
query: { id: script.name },
|
||||
}}
|
||||
>
|
||||
View Script
|
||||
@ -120,102 +135,72 @@ export function LatestScripts({ items }: { items: Category[] }) {
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: find way to determine what the most popular scripts are
|
||||
export function MostViewedScripts({ items }: { items: Category[] }) {
|
||||
const mostViewedScripts = items.reduce((acc, category) => {
|
||||
const foundScripts = category.scripts.filter((script) =>
|
||||
mostPopularScripts.includes(script.name),
|
||||
);
|
||||
acc.push(...foundScripts);
|
||||
return acc;
|
||||
}, [] as Script[]);
|
||||
|
||||
// export function MostViewedScripts({ items }: { items: Category[] }) {
|
||||
// const [page, setPage] = useState(1);
|
||||
|
||||
// const mostViewedScripts = useMemo(() => {
|
||||
// if (!items) return [];
|
||||
// const scripts = items.flatMap((category) => category.scripts || []);
|
||||
// const mostViewedScripts = scripts
|
||||
// .filter((script) => script.isMostViewed)
|
||||
// .map((script) => ({
|
||||
// ...script,
|
||||
// }));
|
||||
// return mostViewedScripts;
|
||||
// }, [items]);
|
||||
|
||||
// const goToNextPage = () => {
|
||||
// setPage((prevPage) => prevPage + 1);
|
||||
// };
|
||||
|
||||
// const goToPreviousPage = () => {
|
||||
// setPage((prevPage) => prevPage - 1);
|
||||
// };
|
||||
|
||||
// const startIndex = (page - 1) * ITEMS_PER_PAGE;
|
||||
// const endIndex = page * ITEMS_PER_PAGE;
|
||||
|
||||
// return (
|
||||
// <div className="">
|
||||
// {mostViewedScripts.length > 0 && (
|
||||
// <>
|
||||
// <h2 className="text-lg font-semibold">Most Viewed Scripts</h2>
|
||||
// </>
|
||||
// )}
|
||||
// <div className="min-w flex w-full flex-row flex-wrap gap-4">
|
||||
// {mostViewedScripts.slice(startIndex, endIndex).map((item) => (
|
||||
// <Card
|
||||
// key={item.id}
|
||||
// className="min-w-[250px] flex-1 flex-grow bg-accent/30"
|
||||
// >
|
||||
// <CardHeader>
|
||||
// <CardTitle className="flex items-center gap-3">
|
||||
// <div className="flex max-h-16 min-h-16 min-w-16 max-w-16 items-center justify-center rounded-lg bg-accent p-1">
|
||||
// <Image
|
||||
// unoptimized
|
||||
// src={item.logo}
|
||||
// height={64}
|
||||
// width={64}
|
||||
// alt=""
|
||||
// className="h-11 w-11 object-contain"
|
||||
// />
|
||||
// </div>
|
||||
// <div className="flex flex-col">
|
||||
// <p className="line-clamp-1 text-lg">
|
||||
// {item.title} {item.item_type}
|
||||
// </p>
|
||||
// <p className="flex items-center gap-1 text-sm text-muted-foreground">
|
||||
// <CalendarPlus className="h-4 w-4" />
|
||||
// {extractDate(item.created)}
|
||||
// </p>
|
||||
// </div>
|
||||
// </CardTitle>
|
||||
// </CardHeader>
|
||||
// <CardContent>
|
||||
// <CardDescription className="line-clamp-3 text-card-foreground break-words">
|
||||
// {item.description}
|
||||
// </CardDescription>
|
||||
// </CardContent>
|
||||
// <CardFooter className="">
|
||||
// <Button asChild variant="outline">
|
||||
// <Link
|
||||
// href={{
|
||||
// pathname: "/scripts",
|
||||
// query: { id: item.title },
|
||||
// }}
|
||||
// prefetch={false}
|
||||
// >
|
||||
// View Script
|
||||
// </Link>
|
||||
// </Button>
|
||||
// </CardFooter>
|
||||
// </Card>
|
||||
// ))}
|
||||
// </div>
|
||||
// <div className="flex justify-end gap-1 p-2">
|
||||
// {page > 1 && (
|
||||
// <Button onClick={goToPreviousPage} variant="outline">
|
||||
// Previous
|
||||
// </Button>
|
||||
// )}
|
||||
// {endIndex < mostViewedScripts.length && (
|
||||
// <Button onClick={goToNextPage} variant="outline">
|
||||
// {page === 1 ? "More.." : "Next"}
|
||||
// </Button>
|
||||
// )}
|
||||
// </div>
|
||||
// </div>
|
||||
// );
|
||||
// }
|
||||
return (
|
||||
<div className="">
|
||||
{mostViewedScripts.length > 0 && (
|
||||
<>
|
||||
<h2 className="text-lg font-semibold">Most Viewed Scripts</h2>
|
||||
</>
|
||||
)}
|
||||
<div className="min-w flex w-full flex-row flex-wrap gap-4">
|
||||
{mostViewedScripts.map((script) => (
|
||||
<Card
|
||||
key={script.name}
|
||||
className="min-w-[250px] flex-1 flex-grow bg-accent/30"
|
||||
>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-3">
|
||||
<div className="flex max-h-16 min-h-16 min-w-16 max-w-16 items-center justify-center rounded-lg bg-accent p-1">
|
||||
<Image
|
||||
unoptimized
|
||||
src={script.logo || "/logo.png"}
|
||||
height={64}
|
||||
width={64}
|
||||
alt=""
|
||||
className="h-11 w-11 object-contain"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col">
|
||||
<p className="line-clamp-1 text-lg">
|
||||
{script.name} {getCorrectTypeNaming(script.type)}
|
||||
</p>
|
||||
<p className="flex items-center gap-1 text-sm text-muted-foreground">
|
||||
<CalendarPlus className="h-4 w-4" />
|
||||
{extractDate(script.date_created)}
|
||||
</p>
|
||||
</div>
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<CardDescription className="line-clamp-3 text-card-foreground break-words">
|
||||
{script.description}
|
||||
</CardDescription>
|
||||
</CardContent>
|
||||
<CardFooter className="">
|
||||
<Button asChild variant="outline">
|
||||
<Link
|
||||
href={{
|
||||
pathname: "/scripts",
|
||||
query: { id: script.name },
|
||||
}}
|
||||
prefetch={false}
|
||||
>
|
||||
View Script
|
||||
</Link>
|
||||
</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import Sidebar from "./_components/Sidebar";
|
||||
import { useQueryState } from "nuqs";
|
||||
import {
|
||||
LatestScripts,
|
||||
// MostViewedScripts,
|
||||
MostViewedScripts,
|
||||
} from "./_components/ScriptInfoBlocks";
|
||||
import { fetchCategories } from "@/lib/pocketbase";
|
||||
|
||||
@ -53,7 +53,7 @@ function ScriptContent() {
|
||||
) : (
|
||||
<div className="flex w-full flex-col gap-5">
|
||||
<LatestScripts items={links} />
|
||||
{/* <MostViewedScripts items={links} /> */}
|
||||
<MostViewedScripts items={links} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
@ -21,3 +21,9 @@ export const navbarLinks = [
|
||||
text: "Discussions",
|
||||
},
|
||||
];
|
||||
|
||||
export const mostPopularScripts = [
|
||||
"Proxmox VE Post Install",
|
||||
"Docker",
|
||||
"Home Assistant OS",
|
||||
];
|
Loading…
Reference in New Issue
Block a user