diff --git a/gui/app/page.tsx b/gui/app/page.tsx index 6329f4b..4f114c9 100644 --- a/gui/app/page.tsx +++ b/gui/app/page.tsx @@ -1,5 +1,61 @@ "use client"; +import { PACK_ENDPOINT, PACKS_ENDPOINT } from "@/api/ENDPOINTS"; +import { Pack } from "@/types/pack"; +import { Card, Spinner } from "flowbite-react"; +import Link from "next/link"; +import { useEffect, useState } from "react"; + export default function Home() { - return <> + const [packsData, setPacksData] = useState([]); + const [packsDataLoading, setPacksDataLoading] = useState(true); + + useEffect(() => { + async function _getPacksData() { + const res = await fetch(PACKS_ENDPOINT("getPacks")); + setPacksData(await res.json()); + setPacksDataLoading(false); + } + _getPacksData(); + }, []); + + return ( +
+ {packsDataLoading && ( +
+ +
+ )} + {!packsDataLoading && ( +
+ {packsData.map((pack) => { + return ( + + +
+ {/* eslint-disable-next-line @next/next/no-img-element */} + +
+

{pack.title}

+

by {pack.author}

+
+
+
+

{pack.modloader}

+

{pack.version}

+ | +

{pack.mods.length} mods

+
+
+ + ); + })} +
+ )} +
+ ); } diff --git a/gui/types/file.ts b/gui/types/file.ts new file mode 100644 index 0000000..817dafd --- /dev/null +++ b/gui/types/file.ts @@ -0,0 +1,7 @@ +export type ModFile = { + "version": string, + "hashes": unknown, + "url": string, + "filename": string, + "size": number, +} \ No newline at end of file diff --git a/gui/types/mod.ts b/gui/types/mod.ts new file mode 100644 index 0000000..7bb415c --- /dev/null +++ b/gui/types/mod.ts @@ -0,0 +1,15 @@ +import { ModFile } from "./file"; + +export type Mod = { + "slug": string, + "icon": string, + "title":string, + "developers": string[], + "source": string, + "url": string, + "environment": { + "client": boolean, + "server": boolean, + }, + "file": ModFile, +} \ No newline at end of file diff --git a/gui/types/pack.ts b/gui/types/pack.ts new file mode 100644 index 0000000..6ab278c --- /dev/null +++ b/gui/types/pack.ts @@ -0,0 +1,13 @@ +import { Mod } from "./mod"; + +export type Pack = { + _id: string; + formatVersion: number; + modpackVersion: number; + title: string; + author: string; + version: string; + modloader: string; + updateURL: ""; + mods: Mod[]; +}; diff --git a/src/api/pack.py b/src/api/pack.py index ef4174b..c77b0f5 100644 --- a/src/api/pack.py +++ b/src/api/pack.py @@ -1,7 +1,7 @@ import os import re from . import apiPack -from flask import request, jsonify, send_file, redirect +from flask import request, jsonify, send_file, redirect, url_for from config import PACKS_FOLDER, IMG_ALLOWED_MIME from PIL import Image from io import BytesIO @@ -11,7 +11,7 @@ import base64 @apiPack.route("//image", methods=["GET"]) def getPackImage(id): if not os.path.exists(f"{PACKS_FOLDER}/{id}/packicon.png"): - return redirect("/favicon.ico") + return redirect(url_for("static", filename="defaulticon.png")) return send_file(f"{PACKS_FOLDER}/{id}/packicon.png") diff --git a/src/api/packs.py b/src/api/packs.py index 590befd..8d788b3 100644 --- a/src/api/packs.py +++ b/src/api/packs.py @@ -5,6 +5,26 @@ from config import PACKS_FOLDER import json +@apiPacks.route("/all", methods=["GET"]) +def getPacks(): + packs = [] + + if not os.path.exists(f"{PACKS_FOLDER}"): + os.makedirs(f"{PACKS_FOLDER}", exist_ok=True) + return jsonify(packs) + + pack_folders = [f.name for f in os.scandir(PACKS_FOLDER) if f.is_dir()] + for pack_folder in pack_folders: + if not os.path.exists(f"{PACKS_FOLDER}/{pack_folder}/packfile.json"): + continue + with open(f"{PACKS_FOLDER}/{pack_folder}/packfile.json") as fp: + pack = json.load(fp) + pack["_id"] = pack_folder + packs.append(pack) + fp.close() + return jsonify(packs) + + @apiPacks.route("/new", methods=["POST"]) def createPack(): pack = { diff --git a/src/static/defaulticon.png b/src/static/defaulticon.png new file mode 100644 index 0000000..0c58d0d Binary files /dev/null and b/src/static/defaulticon.png differ