diff --git a/frontend/next.config.mjs b/frontend/next.config.mjs index 108da034e..48199ca6a 100644 --- a/frontend/next.config.mjs +++ b/frontend/next.config.mjs @@ -18,6 +18,10 @@ const nextConfig = { BASE_PATH: "ProxmoxVE", }, + eslint: { + ignoreDuringBuilds: true, + }, + output: "export", basePath: `/ProxmoxVE`, }; diff --git a/frontend/src/app/category-view/page.tsx b/frontend/src/app/category-view/page.tsx index 97e06ec0d..065d505e3 100644 --- a/frontend/src/app/category-view/page.tsx +++ b/frontend/src/app/category-view/page.tsx @@ -73,7 +73,13 @@ function CategoryView() { }; const handleScriptClick = (scriptSlug: string) => { - router.push(`/scripts?id=${scriptSlug}`); + // Include category context when navigating to scripts + const categoryName = selectedCategoryIndex !== null ? categories[selectedCategoryIndex]?.name : null; + const queryParams = new URLSearchParams({ id: scriptSlug }); + if (categoryName) { + queryParams.append("category", categoryName); + } + router.push(`/scripts?${queryParams.toString()}`); }; const navigateCategory = (direction: "prev" | "next") => { diff --git a/frontend/src/app/scripts/_components/script-accordion.tsx b/frontend/src/app/scripts/_components/script-accordion.tsx index c270f0021..0730efcaf 100644 --- a/frontend/src/app/scripts/_components/script-accordion.tsx +++ b/frontend/src/app/scripts/_components/script-accordion.tsx @@ -4,12 +4,7 @@ import Link from "next/link"; import type { Category } from "@/lib/types"; -import { - Accordion, - AccordionContent, - AccordionItem, - AccordionTrigger, -} from "@/components/ui/accordion"; +import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion"; import { formattedBadge } from "@/components/command-menu"; import { basePath } from "@/config/site-config"; import { cn } from "@/lib/utils"; @@ -18,14 +13,16 @@ export default function ScriptAccordion({ items, selectedScript, setSelectedScript, + selectedCategory, + setSelectedCategory, }: { items: Category[]; selectedScript: string | null; setSelectedScript: (script: string | null) => void; + selectedCategory: string | null; + setSelectedCategory: (category: string | null) => void; }) { - const [expandedItem, setExpandedItem] = useState( - undefined, - ); + const [expandedItem, setExpandedItem] = useState(undefined); const linkRefs = useRef<{ [key: string]: HTMLAnchorElement | null }>({}); const handleAccordionChange = (value: string | undefined) => { @@ -41,15 +38,27 @@ export default function ScriptAccordion({ useEffect(() => { if (selectedScript) { - const category = items.find(category => - category.scripts.some(script => script.slug === selectedScript), - ); + let category; + + // If we have a selected category, try to find the script in that specific category + if (selectedCategory) { + category = items.find( + cat => cat.name === selectedCategory && cat.scripts.some(script => script.slug === selectedScript), + ); + } + + // Fallback: if no category is selected or script not found in selected category, + // use the first category containing the script (backward compatibility) + if (!category) { + category = items.find(category => category.scripts.some(script => script.slug === selectedScript)); + } + if (category) { setExpandedItem(category.name); handleSelected(selectedScript); } } - }, [selectedScript, items, handleSelected]); + }, [selectedScript, selectedCategory, items, handleSelected]); return ( {" "} - + {category.scripts .slice() .sort((a, b) => a.name.localeCompare(b.name)) @@ -94,7 +100,7 @@ export default function ScriptAccordion({ handleSelected(script.slug)} + onClick={() => { + handleSelected(script.slug); + setSelectedCategory(category.name); + }} ref={(el) => { linkRefs.current[script.slug] = el; }} @@ -113,15 +122,11 @@ export default function ScriptAccordion({ height={16} width={16} unoptimized - onError={e => - ((e.currentTarget as HTMLImageElement).src - = `/${basePath}/logo.png`)} + onError={e => ((e.currentTarget as HTMLImageElement).src = `/${basePath}/logo.png`)} alt={script.name} className="mr-1 w-4 h-4 rounded-full" /> - - {script.name} - + {script.name} {formattedBadge(script.type)} diff --git a/frontend/src/app/scripts/_components/sidebar.tsx b/frontend/src/app/scripts/_components/sidebar.tsx index 8b2c461c3..aefff1493 100644 --- a/frontend/src/app/scripts/_components/sidebar.tsx +++ b/frontend/src/app/scripts/_components/sidebar.tsx @@ -8,10 +8,14 @@ function Sidebar({ items, selectedScript, setSelectedScript, + selectedCategory, + setSelectedCategory, }: { items: Category[]; selectedScript: string | null; setSelectedScript: (script: string | null) => void; + selectedCategory: string | null; + setSelectedCategory: (category: string | null) => void; }) { const uniqueScripts = items.reduce((acc, category) => { for (const script of category.scripts) { @@ -37,6 +41,8 @@ function Sidebar({ items={items} selectedScript={selectedScript} setSelectedScript={setSelectedScript} + selectedCategory={selectedCategory} + setSelectedCategory={setSelectedCategory} /> diff --git a/frontend/src/app/scripts/page.tsx b/frontend/src/app/scripts/page.tsx index 309f8abfd..906611216 100644 --- a/frontend/src/app/scripts/page.tsx +++ b/frontend/src/app/scripts/page.tsx @@ -8,16 +8,14 @@ import type { Category, Script } from "@/lib/types"; import { ScriptItem } from "@/app/scripts/_components/script-item"; import { fetchCategories } from "@/lib/data"; -import { - LatestScripts, - MostViewedScripts, -} from "./_components/script-info-blocks"; +import { LatestScripts, MostViewedScripts } from "./_components/script-info-blocks"; import Sidebar from "./_components/sidebar"; export const dynamic = "force-static"; function ScriptContent() { const [selectedScript, setSelectedScript] = useQueryState("id"); + const [selectedCategory, setSelectedCategory] = useQueryState("category"); const [links, setLinks] = useState([]); const [item, setItem] = useState