diff --git a/frontend/src/app/api/categories/route.ts b/frontend/src/app/api/categories/route.ts deleted file mode 100644 index b603d9c..0000000 --- a/frontend/src/app/api/categories/route.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { Metadata, Script } from "@/lib/types"; -import { promises as fs } from "fs"; -import { NextResponse } from "next/server"; -import path from "path"; - -export const dynamic = "force-static"; - -const publicJsonPath = path.join(process.cwd(), 'public/json'); -const getJsonDirectory = async () => { - if (!(await fs.stat(publicJsonPath).catch(() => null))) { - throw new Error(`JSON path file not found: ${publicJsonPath}`); - } - const jsonPath = (await fs.readFile(publicJsonPath, "utf-8")).trim(); - return path.resolve(process.cwd(), jsonPath); -}; - -const jsonDir = await getJsonDirectory(); -const metadataFileName = "metadata.json"; -const encoding = "utf-8"; - -const getMetadata = async () => { - const filePath = path.resolve(jsonDir, metadataFileName); - const fileContent = await fs.readFile(filePath, encoding); - const metadata: Metadata = JSON.parse(fileContent); - return metadata; -}; - -const getScripts = async () => { - const filePaths = (await fs.readdir(jsonDir)) - .filter((fileName) => fileName !== metadataFileName) - .map((fileName) => path.resolve(jsonDir, fileName)); - - const scripts = await Promise.all( - filePaths.map(async (filePath) => { - const fileContent = await fs.readFile(filePath, encoding); - const script: Script = JSON.parse(fileContent); - return script; - }), - ); - return scripts; -}; - -export async function GET() { - try { - const metadata = await getMetadata(); - const scripts = await getScripts(); - - const categories = metadata.categories - .map((category) => { - category.scripts = scripts.filter((script) => - script.categories.includes(category.id), - ); - return category; - }) - .sort((a, b) => a.sort_order - b.sort_order); - - return NextResponse.json(categories); - } catch (error) { - console.error(error as Error); - return NextResponse.json( - { error: "Failed to fetch categories" }, - { status: 500 }, - ); - } -} diff --git a/frontend/src/app/data/page.tsx b/frontend/src/app/data/page.tsx deleted file mode 100644 index b752464..0000000 --- a/frontend/src/app/data/page.tsx +++ /dev/null @@ -1,198 +0,0 @@ -"use client"; - -import React, { JSX, useEffect, useState } from "react"; -import DatePicker from 'react-datepicker'; -import 'react-datepicker/dist/react-datepicker.css'; -import ApplicationChart from "../../components/ApplicationChart"; - -interface DataModel { - id: number; - ct_type: number; - disk_size: number; - core_count: number; - ram_size: number; - os_type: string; - os_version: string; - disableip6: string; - nsapp: string; - created_at: string; - method: string; - pve_version: string; - status: string; - error: string; - type: string; - [key: string]: any; -} - -interface SummaryData { - total_entries: number; - status_count: Record; - nsapp_count: Record; -} - -const DataFetcher: React.FC = () => { - const [data, setData] = useState([]); - const [summary, setSummary] = useState(null); - const [loading, setLoading] = useState(true); - const [error, setError] = useState(null); - const [currentPage, setCurrentPage] = useState(1); - const [itemsPerPage, setItemsPerPage] = useState(25); - const [sortConfig, setSortConfig] = useState<{ key: string; direction: 'ascending' | 'descending' } | null>(null); - - useEffect(() => { - const fetchSummary = async () => { - try { - const response = await fetch("https://api.htl-braunau.at/data/summary"); - if (!response.ok) throw new Error(`Failed to fetch summary: ${response.statusText}`); - const result: SummaryData = await response.json(); - setSummary(result); - } catch (err) { - setError((err as Error).message); - } - }; - - fetchSummary(); - }, []); - - useEffect(() => { - const fetchPaginatedData = async () => { - setLoading(true); - try { - const response = await fetch(`https://api.htl-braunau.at/data/paginated?page=${currentPage}&limit=${itemsPerPage === 0 ? '' : itemsPerPage}`); - if (!response.ok) throw new Error(`Failed to fetch data: ${response.statusText}`); - const result: DataModel[] = await response.json(); - setData(result); - } catch (err) { - setError((err as Error).message); - } finally { - setLoading(false); - } - }; - - fetchPaginatedData(); - }, [currentPage, itemsPerPage]); - - const sortedData = React.useMemo(() => { - if (!sortConfig) return data; - const sorted = [...data].sort((a, b) => { - if (a[sortConfig.key] < b[sortConfig.key]) { - return sortConfig.direction === 'ascending' ? -1 : 1; - } - if (a[sortConfig.key] > b[sortConfig.key]) { - return sortConfig.direction === 'ascending' ? 1 : -1; - } - return 0; - }); - return sorted; - }, [data, sortConfig]); - - if (loading) return

Loading...

; - if (error) return

Error: {error}

; - - const requestSort = (key: string) => { - let direction: 'ascending' | 'descending' = 'ascending'; - if (sortConfig && sortConfig.key === key && sortConfig.direction === 'ascending') { - direction = 'descending'; - } - setSortConfig({ key, direction }); - }; - - const formatDate = (dateString: string): string => { - const date = new Date(dateString); - const year = date.getFullYear(); - const month = date.getMonth() + 1; - const day = date.getDate(); - const hours = String(date.getHours()).padStart(2, '0'); - const minutes = String(date.getMinutes()).padStart(2, '0'); - const timezoneOffset = dateString.slice(-6); - return `${day}.${month}.${year} ${hours}:${minutes} ${timezoneOffset} GMT`; - }; - - return ( -
-

Created LXCs

- -

-
-

{summary?.total_entries} results found

-

Status Legend: 🔄 installing {summary?.status_count["installing"] ?? 0} | ✔️ completed {summary?.status_count["done"] ?? 0} | ❌ failed {summary?.status_count["failed"] ?? 0} | ❓ unknown

-
-
-
- - - - - - - - - - - - - - - - - - - {sortedData.map((item, index) => ( - - - - - - - - - - - - - - - ))} - -
requestSort('status')}>Status requestSort('type')}>Type requestSort('nsapp')}>Application requestSort('os_type')}>OS requestSort('os_version')}>OS Version requestSort('disk_size')}>Disk Size requestSort('core_count')}>Core Count requestSort('ram_size')}>RAM Size requestSort('method')}>Method requestSort('pve_version')}>PVE Version requestSort('error')}>Error Message requestSort('created_at')}>Created At
- {item.status === "done" ? ( - "✔️" - ) : item.status === "failed" ? ( - "❌" - ) : item.status === "installing" ? ( - "🔄" - ) : ( - item.status - )} - {item.type === "lxc" ? ( - "📦" - ) : item.type === "vm" ? ( - "🖥️" - ) : ( - item.type - )}{item.nsapp}{item.os_type}{item.os_version}{item.disk_size}{item.core_count}{item.ram_size}{item.method}{item.pve_version}{item.error}{formatDate(item.created_at)}
-
-
-
- - Page {currentPage} - - -
-
- ); -}; - -export default DataFetcher;