mirror of
https://github.com/community-scripts/Proxmox.git
synced 2026-03-31 06:34:15 -04:00
put the script browser inside a separate component for better readability
This commit is contained in:
@@ -5,47 +5,47 @@
|
||||
@layer base {
|
||||
:root {
|
||||
--background: 0 0% 100%;
|
||||
--foreground: 240 10% 3.9%;
|
||||
--foreground: 20 14.3% 4.1%;
|
||||
--card: 0 0% 100%;
|
||||
--card-foreground: 240 10% 3.9%;
|
||||
--card-foreground: 20 14.3% 4.1%;
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 240 10% 3.9%;
|
||||
--primary: 240 5.9% 10%;
|
||||
--primary-foreground: 0 0% 98%;
|
||||
--secondary: 240 4.8% 95.9%;
|
||||
--secondary-foreground: 240 5.9% 10%;
|
||||
--muted: 240 4.8% 95.9%;
|
||||
--muted-foreground: 240 3.8% 46.1%;
|
||||
--accent: 240 4.8% 95.9%;
|
||||
--accent-foreground: 240 5.9% 10%;
|
||||
--popover-foreground: 20 14.3% 4.1%;
|
||||
--primary: 24.6 95% 53.1%;
|
||||
--primary-foreground: 60 9.1% 97.8%;
|
||||
--secondary: 60 4.8% 95.9%;
|
||||
--secondary-foreground: 24 9.8% 10%;
|
||||
--muted: 60 4.8% 95.9%;
|
||||
--muted-foreground: 25 5.3% 44.7%;
|
||||
--accent: 60 4.8% 95.9%;
|
||||
--accent-foreground: 24 9.8% 10%;
|
||||
--destructive: 0 84.2% 60.2%;
|
||||
--destructive-foreground: 0 0% 98%;
|
||||
--border: 240 5.9% 90%;
|
||||
--input: 240 5.9% 90%;
|
||||
--ring: 240 5.9% 10%;
|
||||
--destructive-foreground: 60 9.1% 97.8%;
|
||||
--border: 20 5.9% 90%;
|
||||
--input: 20 5.9% 90%;
|
||||
--ring: 24.6 95% 53.1%;
|
||||
--radius: 0.5rem;
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: 240 10% 3.9%;
|
||||
--foreground: 0 0% 98%;
|
||||
--card: 240 10% 3.9%;
|
||||
--card-foreground: 0 0% 98%;
|
||||
--popover: 240 10% 3.9%;
|
||||
--popover-foreground: 0 0% 98%;
|
||||
--primary: 201 100% 38%;
|
||||
--primary-foreground: 240 5.9% 10%;
|
||||
--secondary: 240 3.7% 15.9%;
|
||||
--secondary-foreground: 0 0% 98%;
|
||||
--muted: 240 3.7% 15.9%;
|
||||
--muted-foreground: 240 5% 64.9%;
|
||||
--accent: 240 3.7% 15.9%;
|
||||
--accent-foreground: 0 0% 98%;
|
||||
--destructive: 0 62.8% 30.6%;
|
||||
--destructive-foreground: 0 0% 98%;
|
||||
--border: 240 3.7% 15.9%;
|
||||
--input: 240 3.7% 15.9%;
|
||||
--ring: 240 4.9% 83.9%;
|
||||
--background: 20 14.3% 4.1%;
|
||||
--foreground: 60 9.1% 97.8%;
|
||||
--card: 20 14.3% 4.1%;
|
||||
--card-foreground: 60 9.1% 97.8%;
|
||||
--popover: 20 14.3% 4.1%;
|
||||
--popover-foreground: 60 9.1% 97.8%;
|
||||
--primary: 20.5 90.2% 48.2%;
|
||||
--primary-foreground: 60 9.1% 97.8%;
|
||||
--secondary: 12 6.5% 15.1%;
|
||||
--secondary-foreground: 60 9.1% 97.8%;
|
||||
--muted: 12 6.5% 15.1%;
|
||||
--muted-foreground: 24 5.4% 63.9%;
|
||||
--accent: 12 6.5% 15.1%;
|
||||
--accent-foreground: 60 9.1% 97.8%;
|
||||
--destructive: 0 72.2% 50.6%;
|
||||
--destructive-foreground: 60 9.1% 97.8%;
|
||||
--border: 12 6.5% 15.1%;
|
||||
--input: 12 6.5% 15.1%;
|
||||
--ring: 20.5 90.2% 48.2%;
|
||||
}
|
||||
}
|
||||
@layer base {
|
||||
@@ -55,12 +55,4 @@
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
}
|
||||
}
|
||||
|
||||
[data-state="open"] .accordioncontent {
|
||||
display: block;
|
||||
}
|
||||
|
||||
[data-state="closed"] .accordioncontent {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -1,62 +1,8 @@
|
||||
"use client";
|
||||
import React, { useEffect, useState, useRef } from "react";
|
||||
import {
|
||||
Accordion,
|
||||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
AccordionContent,
|
||||
} from "@/components/ui/accordion";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import ScriptItem from "@/components/Script";
|
||||
import { Category } from "@/lib/types";
|
||||
import Link from "next/link";
|
||||
import ScriptBrowser from "@/components/ScriptBrowser";
|
||||
import Particles from "@/components/ui/particles";
|
||||
|
||||
export default function Page() {
|
||||
const [selectedItem, setSelectedItem] = useState("");
|
||||
const [links, setLinks] = useState<Category[]>([]);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (event: any) => {
|
||||
if (event.key === "/") {
|
||||
if (inputRef.current) {
|
||||
inputRef.current.focus();
|
||||
}
|
||||
event.preventDefault();
|
||||
}
|
||||
};
|
||||
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
const data = await getLinks();
|
||||
setLinks(data);
|
||||
} catch (error) {
|
||||
console.error("Error fetching links:", error);
|
||||
}
|
||||
};
|
||||
fetchData();
|
||||
|
||||
document.addEventListener("keydown", handleKeyDown);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener("keydown", handleKeyDown);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const getLinks = async () => {
|
||||
const res = await fetch(
|
||||
`${process.env.NEXT_PUBLIC_POCKETBASE_URL}/api/collections/proxmox_items/records`,
|
||||
);
|
||||
const data = await res.json();
|
||||
return data.items as Category[];
|
||||
};
|
||||
|
||||
const handleSearch = (value: string) => {
|
||||
setSearchTerm(value);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Particles
|
||||
@@ -64,62 +10,7 @@ export default function Page() {
|
||||
quantity={100}
|
||||
/>
|
||||
<div className="mt-20 flex">
|
||||
<div className="flex min-w-72 max-w-72 flex-col">
|
||||
<h1 className="mb-5 text-xl font-bold">Scripts</h1>
|
||||
<Input
|
||||
className="mb-5"
|
||||
type="text"
|
||||
placeholder="Type '/' to search"
|
||||
onChange={(e) => handleSearch(e.target.value)}
|
||||
ref={inputRef}
|
||||
/>
|
||||
<Accordion
|
||||
type={searchTerm ? "multiple" : "single"}
|
||||
{...(searchTerm ? {} : { collapsible: true })}
|
||||
>
|
||||
{links.map(
|
||||
(category) =>
|
||||
category.Items.filter(
|
||||
(script) =>
|
||||
!searchTerm ||
|
||||
script.title
|
||||
.toLowerCase()
|
||||
.includes(searchTerm.toLowerCase()),
|
||||
).length > 0 && (
|
||||
<AccordionItem
|
||||
value={category.id}
|
||||
key={category.id}
|
||||
className={`text-md flex flex-col gap-2`}
|
||||
>
|
||||
<AccordionTrigger>
|
||||
{category.Catagory_Title}
|
||||
</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
{category.Items.filter(
|
||||
(script) =>
|
||||
!searchTerm ||
|
||||
script.title
|
||||
.toLowerCase()
|
||||
.includes(searchTerm.toLowerCase()),
|
||||
).map((script, index) => (
|
||||
<p key={index} className="py-1">
|
||||
<Link
|
||||
href={{
|
||||
pathname: "/scripts",
|
||||
query: { id: script.scriptID },
|
||||
}}
|
||||
className="text-muted-foreground"
|
||||
>
|
||||
{script.title}
|
||||
</Link>
|
||||
</p>
|
||||
))}
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
),
|
||||
)}
|
||||
</Accordion>
|
||||
</div>
|
||||
<ScriptBrowser />
|
||||
<div className="flex">
|
||||
<div className="h-screen w-full">
|
||||
<ScriptItem />
|
||||
|
||||
125
components/ScriptBrowser.tsx
Normal file
125
components/ScriptBrowser.tsx
Normal file
@@ -0,0 +1,125 @@
|
||||
'use client'
|
||||
import {
|
||||
Accordion,
|
||||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
AccordionContent,
|
||||
} from "@/components/ui/accordion";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import Link from "next/link";
|
||||
import React, { useEffect, useState, useRef } from "react";
|
||||
import { Category } from "@/lib/types";
|
||||
|
||||
function ScriptBrowser() {
|
||||
const [selectedItem, setSelectedItem] = useState("");
|
||||
const [links, setLinks] = useState<Category[]>([]);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const [isSearch, setIsSearch] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (event: any) => {
|
||||
if (event.key === "/") {
|
||||
if (inputRef.current) {
|
||||
inputRef.current.focus();
|
||||
}
|
||||
event.preventDefault();
|
||||
}
|
||||
};
|
||||
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
const data = await getLinks();
|
||||
setLinks(data);
|
||||
} catch (error) {
|
||||
console.error("Error fetching links:", error);
|
||||
}
|
||||
};
|
||||
fetchData();
|
||||
|
||||
document.addEventListener("keydown", handleKeyDown);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener("keydown", handleKeyDown);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const getLinks = async () => {
|
||||
const res = await fetch(
|
||||
`${process.env.NEXT_PUBLIC_POCKETBASE_URL}/api/collections/proxmox_items/records`,
|
||||
);
|
||||
const data = await res.json();
|
||||
return data.items as Category[];
|
||||
};
|
||||
|
||||
const handleSearch = (value: string) => {
|
||||
setSearchTerm(value);
|
||||
if (value.length > 0) {
|
||||
setIsSearch(true);
|
||||
} else {
|
||||
setIsSearch(false);
|
||||
}
|
||||
};
|
||||
return (
|
||||
<>
|
||||
{" "}
|
||||
<div className="flex min-w-72 max-w-72 flex-col">
|
||||
<h1 className="mb-5 text-xl font-bold">Scripts</h1>
|
||||
<Input
|
||||
className="mb-5"
|
||||
type="text"
|
||||
placeholder="Type '/' to search"
|
||||
onChange={(e) => handleSearch(e.target.value)}
|
||||
ref={inputRef}
|
||||
/>
|
||||
<Accordion
|
||||
type={searchTerm ? "multiple" : "single"}
|
||||
{...(searchTerm ? {} : { collapsible: true })}
|
||||
>
|
||||
{links.map(
|
||||
(category) =>
|
||||
category.Items.filter(
|
||||
(script) =>
|
||||
!searchTerm ||
|
||||
script.title.toLowerCase().includes(searchTerm.toLowerCase()),
|
||||
).length > 0 && (
|
||||
<AccordionItem
|
||||
value={category.id}
|
||||
key={category.id}
|
||||
className={`text-md flex flex-col gap-2`}
|
||||
// if search term is present, open the accordion with the [data-state]
|
||||
{...(isSearch ? { "data-state": "open" } : {})}
|
||||
data-state="open"
|
||||
>
|
||||
<AccordionTrigger>{category.Catagory_Title}</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
{category.Items.filter(
|
||||
(script) =>
|
||||
!searchTerm ||
|
||||
script.title
|
||||
.toLowerCase()
|
||||
.includes(searchTerm.toLowerCase()),
|
||||
).map((script, index) => (
|
||||
<p key={index} className="py-1">
|
||||
<Link
|
||||
href={{
|
||||
pathname: "/scripts",
|
||||
query: { id: script.scriptID },
|
||||
}}
|
||||
className="text-muted-foreground"
|
||||
>
|
||||
{script.title}
|
||||
</Link>
|
||||
</p>
|
||||
))}
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
),
|
||||
)}
|
||||
</Accordion>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default ScriptBrowser
|
||||
@@ -2,7 +2,6 @@ import type { Config } from "tailwindcss"
|
||||
|
||||
const svgToDataUri = require("mini-svg-data-uri");
|
||||
|
||||
const colors = require("tailwindcss/colors");
|
||||
const {
|
||||
default: flattenColorPalette,
|
||||
} = require("tailwindcss/lib/util/flattenColorPalette");
|
||||
|
||||
Reference in New Issue
Block a user