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,
|
CardHeader,
|
||||||
CardTitle,
|
CardTitle,
|
||||||
} from "@/components/ui/card";
|
} from "@/components/ui/card";
|
||||||
|
import { mostPopularScripts } from "@/config/siteConfig";
|
||||||
import { extractDate } from "@/lib/time";
|
import { extractDate } from "@/lib/time";
|
||||||
import { Category } from "@/lib/types";
|
import { Category, Script } from "@/lib/types";
|
||||||
import { CalendarPlus } from "lucide-react";
|
import { CalendarPlus } from "lucide-react";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
@ -16,6 +17,19 @@ import { useMemo, useState } from "react";
|
|||||||
|
|
||||||
const ITEMS_PER_PAGE = 3;
|
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[] }) {
|
export function LatestScripts({ items }: { items: Category[] }) {
|
||||||
const [page, setPage] = useState(1);
|
const [page, setPage] = useState(1);
|
||||||
|
|
||||||
@ -23,7 +37,8 @@ export function LatestScripts({ items }: { items: Category[] }) {
|
|||||||
if (!items) return [];
|
if (!items) return [];
|
||||||
const scripts = items.flatMap((category) => category.scripts || []);
|
const scripts = items.flatMap((category) => category.scripts || []);
|
||||||
return scripts.sort(
|
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]);
|
}, [items]);
|
||||||
|
|
||||||
@ -68,16 +83,16 @@ export function LatestScripts({ items }: { items: Category[] }) {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="min-w flex w-full flex-row flex-wrap gap-4">
|
<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
|
<Card
|
||||||
key={item.name}
|
key={script.name}
|
||||||
className="min-w-[250px] flex-1 flex-grow bg-accent/30"
|
className="min-w-[250px] flex-1 flex-grow bg-accent/30"
|
||||||
>
|
>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle className="flex items-center gap-3">
|
<CardTitle className="flex items-center gap-3">
|
||||||
<div className="flex h-16 w-16 items-center justify-center rounded-lg bg-accent p-1">
|
<div className="flex h-16 w-16 items-center justify-center rounded-lg bg-accent p-1">
|
||||||
<Image
|
<Image
|
||||||
src={item.logo || "/logo.png"}
|
src={script.logo || "/logo.png"}
|
||||||
unoptimized
|
unoptimized
|
||||||
height={64}
|
height={64}
|
||||||
width={64}
|
width={64}
|
||||||
@ -87,18 +102,18 @@ export function LatestScripts({ items }: { items: Category[] }) {
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<p className="text-lg line-clamp-1">
|
<p className="text-lg line-clamp-1">
|
||||||
{item.name} {item.type}
|
{script.name} {getCorrectTypeNaming(script.type)}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-sm text-muted-foreground flex items-center gap-1">
|
<p className="text-sm text-muted-foreground flex items-center gap-1">
|
||||||
<CalendarPlus className="h-4 w-4" />
|
<CalendarPlus className="h-4 w-4" />
|
||||||
{extractDate(item.date_created)}
|
{extractDate(script.date_created)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<CardDescription className="line-clamp-3 text-card-foreground">
|
<CardDescription className="line-clamp-3 text-card-foreground">
|
||||||
{item.description}
|
{script.description}
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
<CardFooter className="">
|
<CardFooter className="">
|
||||||
@ -106,7 +121,7 @@ export function LatestScripts({ items }: { items: Category[] }) {
|
|||||||
<Link
|
<Link
|
||||||
href={{
|
href={{
|
||||||
pathname: "/scripts",
|
pathname: "/scripts",
|
||||||
query: { id: item.name },
|
query: { id: script.name },
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
View Script
|
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[] }) {
|
return (
|
||||||
// const [page, setPage] = useState(1);
|
<div className="">
|
||||||
|
{mostViewedScripts.length > 0 && (
|
||||||
// const mostViewedScripts = useMemo(() => {
|
<>
|
||||||
// if (!items) return [];
|
<h2 className="text-lg font-semibold">Most Viewed Scripts</h2>
|
||||||
// const scripts = items.flatMap((category) => category.scripts || []);
|
</>
|
||||||
// const mostViewedScripts = scripts
|
)}
|
||||||
// .filter((script) => script.isMostViewed)
|
<div className="min-w flex w-full flex-row flex-wrap gap-4">
|
||||||
// .map((script) => ({
|
{mostViewedScripts.map((script) => (
|
||||||
// ...script,
|
<Card
|
||||||
// }));
|
key={script.name}
|
||||||
// return mostViewedScripts;
|
className="min-w-[250px] flex-1 flex-grow bg-accent/30"
|
||||||
// }, [items]);
|
>
|
||||||
|
<CardHeader>
|
||||||
// const goToNextPage = () => {
|
<CardTitle className="flex items-center gap-3">
|
||||||
// setPage((prevPage) => prevPage + 1);
|
<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
|
||||||
// const goToPreviousPage = () => {
|
src={script.logo || "/logo.png"}
|
||||||
// setPage((prevPage) => prevPage - 1);
|
height={64}
|
||||||
// };
|
width={64}
|
||||||
|
alt=""
|
||||||
// const startIndex = (page - 1) * ITEMS_PER_PAGE;
|
className="h-11 w-11 object-contain"
|
||||||
// const endIndex = page * ITEMS_PER_PAGE;
|
/>
|
||||||
|
</div>
|
||||||
// return (
|
<div className="flex flex-col">
|
||||||
// <div className="">
|
<p className="line-clamp-1 text-lg">
|
||||||
// {mostViewedScripts.length > 0 && (
|
{script.name} {getCorrectTypeNaming(script.type)}
|
||||||
// <>
|
</p>
|
||||||
// <h2 className="text-lg font-semibold">Most Viewed Scripts</h2>
|
<p className="flex items-center gap-1 text-sm text-muted-foreground">
|
||||||
// </>
|
<CalendarPlus className="h-4 w-4" />
|
||||||
// )}
|
{extractDate(script.date_created)}
|
||||||
// <div className="min-w flex w-full flex-row flex-wrap gap-4">
|
</p>
|
||||||
// {mostViewedScripts.slice(startIndex, endIndex).map((item) => (
|
</div>
|
||||||
// <Card
|
</CardTitle>
|
||||||
// key={item.id}
|
</CardHeader>
|
||||||
// className="min-w-[250px] flex-1 flex-grow bg-accent/30"
|
<CardContent>
|
||||||
// >
|
<CardDescription className="line-clamp-3 text-card-foreground break-words">
|
||||||
// <CardHeader>
|
{script.description}
|
||||||
// <CardTitle className="flex items-center gap-3">
|
</CardDescription>
|
||||||
// <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">
|
</CardContent>
|
||||||
// <Image
|
<CardFooter className="">
|
||||||
// unoptimized
|
<Button asChild variant="outline">
|
||||||
// src={item.logo}
|
<Link
|
||||||
// height={64}
|
href={{
|
||||||
// width={64}
|
pathname: "/scripts",
|
||||||
// alt=""
|
query: { id: script.name },
|
||||||
// className="h-11 w-11 object-contain"
|
}}
|
||||||
// />
|
prefetch={false}
|
||||||
// </div>
|
>
|
||||||
// <div className="flex flex-col">
|
View Script
|
||||||
// <p className="line-clamp-1 text-lg">
|
</Link>
|
||||||
// {item.title} {item.item_type}
|
</Button>
|
||||||
// </p>
|
</CardFooter>
|
||||||
// <p className="flex items-center gap-1 text-sm text-muted-foreground">
|
</Card>
|
||||||
// <CalendarPlus className="h-4 w-4" />
|
))}
|
||||||
// {extractDate(item.created)}
|
</div>
|
||||||
// </p>
|
</div>
|
||||||
// </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>
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
@ -10,7 +10,7 @@ import Sidebar from "./_components/Sidebar";
|
|||||||
import { useQueryState } from "nuqs";
|
import { useQueryState } from "nuqs";
|
||||||
import {
|
import {
|
||||||
LatestScripts,
|
LatestScripts,
|
||||||
// MostViewedScripts,
|
MostViewedScripts,
|
||||||
} from "./_components/ScriptInfoBlocks";
|
} from "./_components/ScriptInfoBlocks";
|
||||||
import { fetchCategories } from "@/lib/pocketbase";
|
import { fetchCategories } from "@/lib/pocketbase";
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ function ScriptContent() {
|
|||||||
) : (
|
) : (
|
||||||
<div className="flex w-full flex-col gap-5">
|
<div className="flex w-full flex-col gap-5">
|
||||||
<LatestScripts items={links} />
|
<LatestScripts items={links} />
|
||||||
{/* <MostViewedScripts items={links} /> */}
|
<MostViewedScripts items={links} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -21,3 +21,9 @@ export const navbarLinks = [
|
|||||||
text: "Discussions",
|
text: "Discussions",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const mostPopularScripts = [
|
||||||
|
"Proxmox VE Post Install",
|
||||||
|
"Docker",
|
||||||
|
"Home Assistant OS",
|
||||||
|
];
|
Loading…
Reference in New Issue
Block a user