From 6eb083bfa0b6ecbff038527466cc4fd7046f8146 Mon Sep 17 00:00:00 2001 From: "CanbiZ (MickLesk)" <47820557+MickLesk@users.noreply.github.com> Date: Mon, 2 Mar 2026 08:57:39 +0100 Subject: [PATCH] fix(frontend): improve detail view badges, addon texts, and HTML title - Show colored type badges (VM/LXC/PVE/ADDON) in detail view matching list view - Display PVE and ADDON labels in script cards instead of empty strings - Show 'Existing LXC or Proxmox Node' as OS for addons instead of generic 'Proxmox Node' - Hide privileged badge for addon scripts - Add specific update hint for addons: 'Run update_ to update' - Set document title to ' | Proxmox VE Helper-Scripts' when a script is selected --- .../_components/script-info-blocks.tsx | 26 ++++++++----------- .../app/scripts/_components/script-item.tsx | 7 +++-- .../_components/script-items/tool-tips.tsx | 13 +++++++--- frontend/src/app/scripts/page.tsx | 5 ++++ 4 files changed, 29 insertions(+), 22 deletions(-) diff --git a/frontend/src/app/scripts/_components/script-info-blocks.tsx b/frontend/src/app/scripts/_components/script-info-blocks.tsx index a69f2428f..f8b6c5348 100644 --- a/frontend/src/app/scripts/_components/script-info-blocks.tsx +++ b/frontend/src/app/scripts/_components/script-info-blocks.tsx @@ -19,8 +19,9 @@ export function getDisplayValueFromType(type: string) { case "vm": return "VM"; case "pve": + return "PVE"; case "addon": - return ""; + return "ADDON"; default: return ""; } @@ -36,10 +37,9 @@ export function LatestScripts({ onPageChange: (page: number) => void; }) { const latestScripts = useMemo(() => { - if (!items) - return []; + if (!items) return []; - const scripts = items.flatMap(category => category.scripts || []); + const scripts = items.flatMap((category) => category.scripts || []); // Filter out duplicates by slug const uniqueScriptsMap = new Map(); @@ -97,7 +97,7 @@ export function LatestScripts({ )}
- {latestScripts.slice(startIndex, endIndex).map(script => ( + {latestScripts.slice(startIndex, endIndex).map((script) => ( @@ -108,15 +108,13 @@ export function LatestScripts({ height={64} width={64} alt="" - onError={e => ((e.currentTarget as HTMLImageElement).src = `/${basePath}/logo.png`)} + onError={(e) => ((e.currentTarget as HTMLImageElement).src = `/${basePath}/logo.png`)} className="h-11 w-11 object-contain" />

- {script.name} - {" "} - {getDisplayValueFromType(script.type)} + {script.name} {getDisplayValueFromType(script.type)}

@@ -149,7 +147,7 @@ export function LatestScripts({ export function MostViewedScripts({ items }: { items: Category[] }) { const mostViewedScripts = items.reduce((acc: Script[], category) => { - const foundScripts = category.scripts.filter(script => mostPopularScripts.includes(script.slug)); + const foundScripts = category.scripts.filter((script) => mostPopularScripts.includes(script.slug)); return acc.concat(foundScripts); }, []); @@ -161,7 +159,7 @@ export function MostViewedScripts({ items }: { items: Category[] }) { )}

- {mostViewedScripts.map(script => ( + {mostViewedScripts.map((script) => ( @@ -172,15 +170,13 @@ export function MostViewedScripts({ items }: { items: Category[] }) { height={64} width={64} alt="" - onError={e => ((e.currentTarget as HTMLImageElement).src = `/${basePath}/logo.png`)} + onError={(e) => ((e.currentTarget as HTMLImageElement).src = `/${basePath}/logo.png`)} className="h-11 w-11 object-contain" />

- {script.name} - {" "} - {getDisplayValueFromType(script.type)} + {script.name} {getDisplayValueFromType(script.type)}

diff --git a/frontend/src/app/scripts/_components/script-item.tsx b/frontend/src/app/scripts/_components/script-item.tsx index c521c8e39..e5ddbebbe 100644 --- a/frontend/src/app/scripts/_components/script-item.tsx +++ b/frontend/src/app/scripts/_components/script-item.tsx @@ -14,6 +14,7 @@ import { basePath } from "@/config/site-config"; import { extractDate } from "@/lib/time"; import DisableDescription from "./script-items/disable-description"; +import { formattedBadge } from "@/components/command-menu"; import { getDisplayValueFromType } from "./script-info-blocks"; import DefaultPassword from "./script-items/default-password"; import InstallCommand from "./script-items/install-command"; @@ -31,7 +32,7 @@ type ScriptItemProps = { function ScriptHeader({ item }: { item: Script }) { const defaultInstallMethod = item.install_methods?.[0]; - const os = defaultInstallMethod?.resources?.os || "Proxmox Node"; + const os = defaultInstallMethod?.resources?.os || (item.type === "addon" ? "Existing LXC or Proxmox Node" : "Proxmox Node"); const version = defaultInstallMethod?.resources?.version || ""; return ( @@ -55,9 +56,7 @@ function ScriptHeader({ item }: { item: Script }) {

{item.name} - - {getDisplayValueFromType(item.type)} - + {formattedBadge(item.type)}

diff --git a/frontend/src/app/scripts/_components/script-items/tool-tips.tsx b/frontend/src/app/scripts/_components/script-items/tool-tips.tsx index f4a6be853..04e2752c9 100644 --- a/frontend/src/app/scripts/_components/script-items/tool-tips.tsx +++ b/frontend/src/app/scripts/_components/script-items/tool-tips.tsx @@ -36,17 +36,24 @@ const TooltipBadge: React.FC = ({ variant, label, content }) => ( export default function Tooltips({ item }: { item: Script }) { return (
- {item.privileged && ( + {item.privileged && item.type !== "addon" && ( )} - {item.updateable && item.type !== "pve" && ( + {item.updateable && item.type !== "pve" && item.type !== "addon" && ( )} - {!item.updateable && item.type !== "pve" && } + {item.updateable && item.type === "addon" && ( + + )} + {!item.updateable && item.type !== "pve" && item.type !== "addon" && }
); } diff --git a/frontend/src/app/scripts/page.tsx b/frontend/src/app/scripts/page.tsx index 034d20cad..d023dedad 100644 --- a/frontend/src/app/scripts/page.tsx +++ b/frontend/src/app/scripts/page.tsx @@ -32,6 +32,11 @@ function ScriptContent() { .flat() .find(script => script.slug === selectedScript); setItem(script); + if (script) { + document.title = `${script.name} | Proxmox VE Helper-Scripts`; + } + } else { + document.title = "Proxmox VE Helper-Scripts"; } }, [selectedScript, links]);