From 76cf85293c3c119c9f02fa430976e1a0939cacf4 Mon Sep 17 00:00:00 2001 From: Bram Suurd Date: Wed, 6 Nov 2024 17:25:02 +0100 Subject: [PATCH] Refactor all components to use data from new API --- .../scripts/_components/ScriptAccordion.tsx | 73 ++++--- .../scripts/_components/ScriptInfoBlocks.tsx | 200 +++++++++--------- .../app/scripts/_components/ScriptItem.tsx | 10 +- .../_components/ScriptItems/Alerts.tsx | 6 +- .../_components/ScriptItems/Buttons.tsx | 18 +- .../ScriptItems/DefaultPassword.tsx | 12 +- .../ScriptItems/DefaultSettings.tsx | 24 ++- .../ScriptItems/InstallCommand.tsx | 49 +++-- .../_components/ScriptItems/Tooltips.tsx | 4 +- .../src/app/scripts/_components/Sidebar.tsx | 2 +- frontend/src/app/scripts/page.tsx | 31 +-- 11 files changed, 207 insertions(+), 222 deletions(-) diff --git a/frontend/src/app/scripts/_components/ScriptAccordion.tsx b/frontend/src/app/scripts/_components/ScriptAccordion.tsx index f81970c8..e5592284 100644 --- a/frontend/src/app/scripts/_components/ScriptAccordion.tsx +++ b/frontend/src/app/scripts/_components/ScriptAccordion.tsx @@ -42,10 +42,10 @@ export default function ScriptAccordion({ useEffect(() => { if (selectedScript) { const category = items.find((category) => - category.expand.items.some((script) => script.title === selectedScript), + category.scripts.some((script) => script.name === selectedScript), ); if (category) { - setExpandedItem(category.catagoryName); + setExpandedItem(category.name); handleSelected(selectedScript); } } @@ -60,81 +60,80 @@ export default function ScriptAccordion({ {items.map((category) => (
- {category.catagoryName} + {category.name} - {category.expand.items.length} + {category.scripts.length}
{" "}
- {category.expand.items + {category.scripts .slice() - .sort((a, b) => a.title.localeCompare(b.title)) + .sort((a, b) => a.name.localeCompare(b.name)) .map((script, index) => (
handleSelected(script.title)} + onClick={() => handleSelected(script.name)} ref={(el) => { - linkRefs.current[script.title] = el; + linkRefs.current[script.name] = el; }} > - - ((e.currentTarget as HTMLImageElement).src = - "/logo.png") - } - alt={script.title} - className="mr-1 w-4 h-4 rounded-full" - /> - - {script.title} - {script.isMostViewed && ( - - )} - +
+ + ((e.currentTarget as HTMLImageElement).src = + "/logo.png") + } + alt={script.name} + className="mr-1 w-4 h-4 rounded-full" + /> + + {script.name} + +
- {script.item_type} + {script.type}
diff --git a/frontend/src/app/scripts/_components/ScriptInfoBlocks.tsx b/frontend/src/app/scripts/_components/ScriptInfoBlocks.tsx index a3ba8a6b..772c40b0 100644 --- a/frontend/src/app/scripts/_components/ScriptInfoBlocks.tsx +++ b/frontend/src/app/scripts/_components/ScriptInfoBlocks.tsx @@ -21,9 +21,9 @@ export function LatestScripts({ items }: { items: Category[] }) { const latestScripts = useMemo(() => { if (!items) return []; - const scripts = items.flatMap((category) => category.expand.items || []); + const scripts = items.flatMap((category) => category.scripts || []); return scripts.sort( - (a, b) => new Date(b.created).getTime() - new Date(a.created).getTime(), + (a, b) => new Date(b.date_created).getTime() - new Date(a.date_created).getTime(), ); }, [items]); @@ -70,14 +70,14 @@ export function LatestScripts({ items }: { items: Category[] }) {
{latestScripts.slice(startIndex, endIndex).map((item) => (

- {item.title} {item.item_type} + {item.name} {item.type}

- {extractDate(item.created)} + {extractDate(item.date_created)}

@@ -106,7 +106,7 @@ export function LatestScripts({ items }: { items: Category[] }) { View Script @@ -120,100 +120,102 @@ export function LatestScripts({ items }: { items: Category[] }) { ); } -export function MostViewedScripts({ items }: { items: Category[] }) { - const [page, setPage] = useState(1); +// TODO: find way to determine what the most popular scripts are - const mostViewedScripts = useMemo(() => { - if (!items) return []; - const scripts = items.flatMap((category) => category.expand.items || []); - const mostViewedScripts = scripts - .filter((script) => script.isMostViewed) - .map((script) => ({ - ...script, - })); - return mostViewedScripts; - }, [items]); +// export function MostViewedScripts({ items }: { items: Category[] }) { +// const [page, setPage] = useState(1); - const goToNextPage = () => { - setPage((prevPage) => prevPage + 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 goToPreviousPage = () => { - setPage((prevPage) => prevPage - 1); - }; +// const goToNextPage = () => { +// setPage((prevPage) => prevPage + 1); +// }; - const startIndex = (page - 1) * ITEMS_PER_PAGE; - const endIndex = page * ITEMS_PER_PAGE; +// const goToPreviousPage = () => { +// setPage((prevPage) => prevPage - 1); +// }; - return ( -
- {mostViewedScripts.length > 0 && ( - <> -

Most Viewed Scripts

- - )} -
- {mostViewedScripts.slice(startIndex, endIndex).map((item) => ( - - - -
- -
-
-

- {item.title} {item.item_type} -

-

- - {extractDate(item.created)} -

-
-
-
- - - {item.description} - - - - - -
- ))} -
-
- {page > 1 && ( - - )} - {endIndex < mostViewedScripts.length && ( - - )} -
-
- ); -} +// const startIndex = (page - 1) * ITEMS_PER_PAGE; +// const endIndex = page * ITEMS_PER_PAGE; + +// return ( +//
+// {mostViewedScripts.length > 0 && ( +// <> +//

Most Viewed Scripts

+// +// )} +//
+// {mostViewedScripts.slice(startIndex, endIndex).map((item) => ( +// +// +// +//
+// +//
+//
+//

+// {item.title} {item.item_type} +//

+//

+// +// {extractDate(item.created)} +//

+//
+//
+//
+// +// +// {item.description} +// +// +// +// +// +//
+// ))} +//
+//
+// {page > 1 && ( +// +// )} +// {endIndex < mostViewedScripts.length && ( +// +// )} +//
+//
+// ); +// } diff --git a/frontend/src/app/scripts/_components/ScriptItem.tsx b/frontend/src/app/scripts/_components/ScriptItem.tsx index d1e273e7..b6e98c40 100644 --- a/frontend/src/app/scripts/_components/ScriptItem.tsx +++ b/frontend/src/app/scripts/_components/ScriptItem.tsx @@ -39,21 +39,21 @@ function ScriptItem({
((e.currentTarget as HTMLImageElement).src = "/logo.png") } height={400} - alt={item.title} + alt={item.name} unoptimized />
-

{item.title}

+

{item.name}

- Date added: {extractDate(item.created)} + Date added: {extractDate(item.date_created)}

@@ -76,7 +76,7 @@ function ScriptItem({

- How to {item.item_type ? "install" : "use"} + How to {item.type ? "install" : "use"}

diff --git a/frontend/src/app/scripts/_components/ScriptItems/Alerts.tsx b/frontend/src/app/scripts/_components/ScriptItems/Alerts.tsx index db54f16d..e4c56e16 100644 --- a/frontend/src/app/scripts/_components/ScriptItems/Alerts.tsx +++ b/frontend/src/app/scripts/_components/ScriptItems/Alerts.tsx @@ -5,12 +5,12 @@ import { Info } from "lucide-react"; export default function Alerts({ item }: { item: Script }) { return ( <> - {item.expand?.alerts?.length > 0 && - item.expand.alerts.map((alert: any, index: number) => ( + {item?.notes?.length > 0 && + item.notes.map((note: any, index: number) => (

- {TextCopyBlock(alert.content)} + {TextCopyBlock(note.text)}

))} diff --git a/frontend/src/app/scripts/_components/ScriptItems/Buttons.tsx b/frontend/src/app/scripts/_components/ScriptItems/Buttons.tsx index 89bc2c0b..fac97c85 100644 --- a/frontend/src/app/scripts/_components/ScriptItems/Buttons.tsx +++ b/frontend/src/app/scripts/_components/ScriptItems/Buttons.tsx @@ -21,12 +21,12 @@ export default function Buttons({ item }: { item: Script }) { }; const sourceUrl = useMemo(() => { - if (item.installCommand) { - const match = item.installCommand.match(pattern); + if (item.install_methods[0]?.script) { + const match = item.install_methods[0].script.match(pattern); return match ? transformUrlToInstallScript(match[0]) : null; } return null; - }, [item.installCommand, pattern]); + }, [item.install_methods, pattern]); return (
@@ -49,17 +49,7 @@ export default function Buttons({ item }: { item: Script }) { )} - {item.post_install && ( - - )} - {item.installCommand && sourceUrl && ( + {item.install_methods[0]?.script && sourceUrl && (
@@ -37,10 +37,10 @@ export default function DefaultPassword({ item }: { item: Script }) { variant={"secondary"} size={"null"} onClick={() => - handleCopy("password", item.expand.default_login.password) + handleCopy("password", item.default_credentials.password ?? "") } > - {item.expand.default_login.password} + {item.default_credentials.password}
diff --git a/frontend/src/app/scripts/_components/ScriptItems/DefaultSettings.tsx b/frontend/src/app/scripts/_components/ScriptItems/DefaultSettings.tsx index 05f3ae62..1e9efd36 100644 --- a/frontend/src/app/scripts/_components/ScriptItems/DefaultSettings.tsx +++ b/frontend/src/app/scripts/_components/ScriptItems/DefaultSettings.tsx @@ -1,35 +1,41 @@ import { Script } from "@/lib/types"; export default function DefaultSettings({ item }: { item: Script }) { - const hasAlpineScript = item?.expand?.alpine_script !== undefined; + const defaultSettings = item.install_methods.find( + (method) => method.type === "default", + ); + + const defaultAlpineSettings = item.install_methods.find( + (method) => method.type === "alpine", + ); return ( <> - {item.default_cpu && ( + {defaultSettings && (

Default settings

- CPU: {item.default_cpu} + CPU: {defaultSettings.resources.cpu}vCPU

- RAM: {item.default_ram} + RAM: {defaultSettings.resources.ram}MB

- HDD: {item.default_hdd} + HDD: {defaultSettings.resources.hdd}GB

)} - {hasAlpineScript && ( + {defaultAlpineSettings && (

Default Alpine settings

- CPU: {item.expand.alpine_script.default_cpu} + CPU: {defaultAlpineSettings?.resources.cpu}vCPU

- RAM: {item.expand.alpine_script.default_ram} + RAM: {defaultAlpineSettings?.resources.ram}MB

- HDD: {item.expand.alpine_script.default_hdd} + HDD: {defaultAlpineSettings?.resources.hdd}GB

)} diff --git a/frontend/src/app/scripts/_components/ScriptItems/InstallCommand.tsx b/frontend/src/app/scripts/_components/ScriptItems/InstallCommand.tsx index 31e1e302..f23554d1 100644 --- a/frontend/src/app/scripts/_components/ScriptItems/InstallCommand.tsx +++ b/frontend/src/app/scripts/_components/ScriptItems/InstallCommand.tsx @@ -2,32 +2,41 @@ import CodeCopyButton from "@/components/ui/code-copy-button"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Script } from "@/lib/types"; +const generateInstallCommand = (script: string) => { + return `bash -c "$(wget -qLO - https://github.com/community-scripts/ProxmoxVE/raw/main/${script})"`; +} + export default function InstallCommand({ item }: { item: Script }) { - const { title, item_type, installCommand, expand } = item; - const hasAlpineScript = expand?.alpine_script !== undefined; + const alpineScript = item.install_methods.find( + (method) => method.type === "alpine", + ); + + const defaultScript = item.install_methods.find( + (method) => method.type === "default" + ); const renderInstructions = (isAlpine = false) => ( <>

{isAlpine ? ( <> - As an alternative option, you can use Alpine Linux and the {title}{" "} - package to create a {title} {item_type} container with faster + As an alternative option, you can use Alpine Linux and the {item.name}{" "} + package to create a {item.name} {item.type} container with faster creation time and minimal system resource usage. You are also obliged to adhere to updates provided by the package maintainer. - ) : item_type ? ( + ) : item.type ? ( <> - To create a new Proxmox VE {title} {item_type}, run the command + To create a new Proxmox VE {item.name} {item.type}, run the command below in the Proxmox VE Shell. ) : ( - <>To use the {title} script, run the command below in the shell. + <>To use the {item.name} script, run the command below in the shell. )}

{isAlpine && (

- To create a new Proxmox VE Alpine-{title} {item_type}, run the command + To create a new Proxmox VE Alpine-{item.name} {item.type}, run the command below in the Proxmox VE Shell

)} @@ -36,7 +45,7 @@ export default function InstallCommand({ item }: { item: Script }) { return (
- {hasAlpineScript ? ( + {alpineScript ? ( Default @@ -44,25 +53,23 @@ export default function InstallCommand({ item }: { item: Script }) { {renderInstructions()} - {installCommand} + {defaultScript?.script} - {expand.alpine_script && ( - <> - {renderInstructions(true)} - - {expand.alpine_script.installCommand} - - - )} + {renderInstructions(true)} + + {generateInstallCommand(alpineScript.script)} + - ) : ( + ) : defaultScript?.script ? ( <> {renderInstructions()} - {installCommand && {installCommand}} + + {generateInstallCommand(defaultScript.script)} + - )} + ) : null}
); } diff --git a/frontend/src/app/scripts/_components/ScriptItems/Tooltips.tsx b/frontend/src/app/scripts/_components/ScriptItems/Tooltips.tsx index f0af794b..7e70b68e 100644 --- a/frontend/src/app/scripts/_components/ScriptItems/Tooltips.tsx +++ b/frontend/src/app/scripts/_components/ScriptItems/Tooltips.tsx @@ -37,11 +37,11 @@ export default function Tooltips({ item }: { item: Script }) { content="This script will be run in a privileged LXC" /> )} - {item.isUpdateable && ( + {item.updateable && ( )}
diff --git a/frontend/src/app/scripts/_components/Sidebar.tsx b/frontend/src/app/scripts/_components/Sidebar.tsx index a993e118..f1618e17 100644 --- a/frontend/src/app/scripts/_components/Sidebar.tsx +++ b/frontend/src/app/scripts/_components/Sidebar.tsx @@ -18,7 +18,7 @@ const Sidebar = ({

Categories

{items.reduce( - (acc, category) => acc + category.expand.items.length, + (acc, category) => acc + category.scripts.length, 0, )}{" "} Total scripts diff --git a/frontend/src/app/scripts/page.tsx b/frontend/src/app/scripts/page.tsx index 2ccbc7fc..0d899aca 100644 --- a/frontend/src/app/scripts/page.tsx +++ b/frontend/src/app/scripts/page.tsx @@ -10,7 +10,7 @@ import Sidebar from "./_components/Sidebar"; import { useQueryState } from "nuqs"; import { LatestScripts, - MostViewedScripts, + // MostViewedScripts, } from "./_components/ScriptInfoBlocks"; function ScriptContent() { @@ -21,39 +21,20 @@ function ScriptContent() { useEffect(() => { if (selectedScript && links.length > 0) { const script = links - .map((category) => category.expand.items) + .map((category) => category.scripts) .flat() - .find((script) => script.title === selectedScript); + .find((script) => script.name === selectedScript); setItem(script); } }, [selectedScript, links]); - const sortCategories = (categories: Category[]): Category[] => { - return categories.sort((a: Category, b: Category) => { - if ( - a.catagoryName === "Proxmox VE Tools" && - b.catagoryName !== "Proxmox VE Tools" - ) { - return -1; - } else if ( - a.catagoryName !== "Proxmox VE Tools" && - b.catagoryName === "Proxmox VE Tools" - ) { - return 1; - } else { - return a.catagoryName.localeCompare(b.catagoryName); - } - }); - }; - useEffect(() => { fetch( - `api/categories?_=${process.env.NEXT_PUBLIC_BUILD_TIME || Date.now()}`, + `api/categories`, ) .then((response) => response.json()) .then((categories) => { - const sortedCategories = sortCategories(categories); - setLinks(sortedCategories); + setLinks(categories); }) .catch((error) => console.error(error)); }, []); @@ -74,7 +55,7 @@ function ScriptContent() { ) : (

- + {/* */}
)}