diff --git a/backend/package.json b/backend/package.json index dc18e1e..7dc22f5 100644 --- a/backend/package.json +++ b/backend/package.json @@ -11,16 +11,17 @@ "keywords": [], "author": "", "license": "ISC", - "packageManager": "pnpm@10.5.2", + "packageManager": "pnpm@10.10.0", "dependencies": { "ajv": "^8.17.1", "bcrypt": "^5.1.1", - "better-sqlite3": "^11.9.1", - "dompurify": "^3.2.4", + "better-sqlite3": "^11.10.0", + "cors": "^2.8.5", + "dompurify": "^3.2.5", "express": "^5.1.0", - "jsdom": "^26.0.0", + "jsdom": "^26.1.0", "jsonwebtoken": "^9.0.2", - "marked": "^15.0.7", + "marked": "^15.0.11", "mysql": "^2.18.1" }, "pnpm": { @@ -30,6 +31,6 @@ ] }, "devDependencies": { - "nodemon": "^3.1.9" + "nodemon": "^3.1.10" } } diff --git a/backend/pnpm-lock.yaml b/backend/pnpm-lock.yaml index d1d6f0f..022a404 100644 --- a/backend/pnpm-lock.yaml +++ b/backend/pnpm-lock.yaml @@ -15,35 +15,38 @@ importers: specifier: ^5.1.1 version: 5.1.1 better-sqlite3: - specifier: ^11.9.1 - version: 11.9.1 + specifier: ^11.10.0 + version: 11.10.0 + cors: + specifier: ^2.8.5 + version: 2.8.5 dompurify: - specifier: ^3.2.4 + specifier: ^3.2.5 version: 3.2.5 express: specifier: ^5.1.0 version: 5.1.0 jsdom: - specifier: ^26.0.0 + specifier: ^26.1.0 version: 26.1.0 jsonwebtoken: specifier: ^9.0.2 version: 9.0.2 marked: - specifier: ^15.0.7 - version: 15.0.10 + specifier: ^15.0.11 + version: 15.0.11 mysql: specifier: ^2.18.1 version: 2.18.1 devDependencies: nodemon: - specifier: ^3.1.9 + specifier: ^3.1.10 version: 3.1.10 packages: - '@asamuzakjp/css-color@3.1.4': - resolution: {integrity: sha512-SeuBV4rnjpFNjI8HSgKUwteuFdkHwkboq31HWzznuqgySQir+jSTczoWVVL4jvOjKjuH80fMDG0Fvg1Sb+OJsA==} + '@asamuzakjp/css-color@3.1.7': + resolution: {integrity: sha512-Ok5fYhtwdyJQmU1PpEv6Si7Y+A4cYb8yNM9oiIJC9TzXPMuN9fvdonKJqcnz9TbFqV6bQ8z0giRq0iaOpGZV2g==} '@csstools/color-helpers@5.0.2': resolution: {integrity: sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==} @@ -124,8 +127,8 @@ packages: resolution: {integrity: sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==} engines: {node: '>= 10.0.0'} - better-sqlite3@11.9.1: - resolution: {integrity: sha512-Ba0KR+Fzxh2jDRhdg6TSH0SJGzb8C0aBY4hR8w8madIdIzzC6Y1+kx5qR6eS1Z+Gy20h6ZU28aeyg0z1VIrShQ==} + better-sqlite3@11.10.0: + resolution: {integrity: sha512-EwhOpyXiOEL/lKzHz9AW1msWFNzGc/z+LzeB3/jnFJpxu+th2yqvzsSWas1v9jgs9+xiXJcD5A8CJxAG2TaghQ==} bignumber.js@9.0.0: resolution: {integrity: sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==} @@ -209,6 +212,10 @@ packages: core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + cors@2.8.5: + resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} + engines: {node: '>= 0.10'} + cssstyle@4.3.1: resolution: {integrity: sha512-ZgW+Jgdd7i52AaLYCriF8Mxqft0gD/R9i9wi6RWBhs1pqdPEzPjym7rvRKi397WmQFf3SlyUsszhw+VVCbx79Q==} engines: {node: '>=18'} @@ -477,8 +484,8 @@ packages: resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==} engines: {node: '>=12', npm: '>=6'} - jwa@1.4.1: - resolution: {integrity: sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==} + jwa@1.4.2: + resolution: {integrity: sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==} jws@3.2.2: resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==} @@ -511,8 +518,8 @@ packages: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} engines: {node: '>=8'} - marked@15.0.10: - resolution: {integrity: sha512-BXzsfFiR2UqXFKRwpugWuCYi9mWd1aX/Yns/X52xWfvfen9lnGEDbJw9ZEjjvLZVqntqT2gX45eYvqb2dIokDw==} + marked@15.0.11: + resolution: {integrity: sha512-1BEXAU2euRCG3xwgLVT1y0xbJEld1XOrmRJpUwRCcy7rxhSCwMrmEu9LXoPhHSCJG41V7YcQ2mjKRr5BA3ITIA==} engines: {node: '>= 18'} hasBin: true @@ -580,8 +587,8 @@ packages: resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} engines: {node: '>= 0.6'} - node-abi@3.74.0: - resolution: {integrity: sha512-c5XK0MjkGBrQPGYG24GBADZud0NCbznxNx0ZkS+ebUTrmV1qTDxPxSL8zEAPURXSbLRWVexxmP4986BziahL5w==} + node-abi@3.75.0: + resolution: {integrity: sha512-OhYaY5sDsIka7H7AtijtI9jwGYLyl29eQn/W623DiN/MIv5sUqc4g7BIDThX+gb7di9f6xK02nkp8sdfFWZLTg==} engines: {node: '>=10'} node-addon-api@5.1.0: @@ -733,8 +740,8 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - semver@7.7.1: - resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} + semver@7.7.2: + resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} engines: {node: '>=10'} hasBin: true @@ -908,8 +915,8 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - ws@8.18.1: - resolution: {integrity: sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==} + ws@8.18.2: + resolution: {integrity: sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -932,7 +939,7 @@ packages: snapshots: - '@asamuzakjp/css-color@3.1.4': + '@asamuzakjp/css-color@3.1.7': dependencies: '@csstools/css-calc': 2.1.3(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3) '@csstools/css-color-parser': 3.0.9(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3) @@ -969,7 +976,7 @@ snapshots: nopt: 5.0.0 npmlog: 5.0.1 rimraf: 3.0.2 - semver: 7.7.1 + semver: 7.7.2 tar: 6.2.1 transitivePeerDependencies: - encoding @@ -1026,7 +1033,7 @@ snapshots: - encoding - supports-color - better-sqlite3@11.9.1: + better-sqlite3@11.10.0: dependencies: bindings: 1.5.0 prebuild-install: 7.1.3 @@ -1121,9 +1128,14 @@ snapshots: core-util-is@1.0.3: {} + cors@2.8.5: + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + cssstyle@4.3.1: dependencies: - '@asamuzakjp/css-color': 3.1.4 + '@asamuzakjp/css-color': 3.1.7 rrweb-cssom: 0.8.0 data-urls@5.0.0: @@ -1410,7 +1422,7 @@ snapshots: whatwg-encoding: 3.1.1 whatwg-mimetype: 4.0.0 whatwg-url: 14.2.0 - ws: 8.18.1 + ws: 8.18.2 xml-name-validator: 5.0.0 transitivePeerDependencies: - bufferutil @@ -1430,9 +1442,9 @@ snapshots: lodash.isstring: 4.0.1 lodash.once: 4.1.1 ms: 2.1.3 - semver: 7.7.1 + semver: 7.7.2 - jwa@1.4.1: + jwa@1.4.2: dependencies: buffer-equal-constant-time: 1.0.1 ecdsa-sig-formatter: 1.0.11 @@ -1440,7 +1452,7 @@ snapshots: jws@3.2.2: dependencies: - jwa: 1.4.1 + jwa: 1.4.2 safe-buffer: 5.2.1 lodash.includes@4.3.0: {} @@ -1463,7 +1475,7 @@ snapshots: dependencies: semver: 6.3.1 - marked@15.0.10: {} + marked@15.0.11: {} math-intrinsics@1.1.0: {} @@ -1513,9 +1525,9 @@ snapshots: negotiator@1.0.0: {} - node-abi@3.74.0: + node-abi@3.75.0: dependencies: - semver: 7.7.1 + semver: 7.7.2 node-addon-api@5.1.0: {} @@ -1530,7 +1542,7 @@ snapshots: ignore-by-default: 1.0.1 minimatch: 3.1.2 pstree.remy: 1.1.8 - semver: 7.7.1 + semver: 7.7.2 simple-update-notifier: 2.0.0 supports-color: 5.5.0 touch: 3.1.1 @@ -1583,7 +1595,7 @@ snapshots: minimist: 1.2.8 mkdirp-classic: 0.5.3 napi-build-utils: 2.0.0 - node-abi: 3.74.0 + node-abi: 3.75.0 pump: 3.0.2 rc: 1.2.8 simple-get: 4.0.1 @@ -1676,7 +1688,7 @@ snapshots: semver@6.3.1: {} - semver@7.7.1: {} + semver@7.7.2: {} send@1.2.0: dependencies: @@ -1747,7 +1759,7 @@ snapshots: simple-update-notifier@2.0.0: dependencies: - semver: 7.7.1 + semver: 7.7.2 sqlstring@2.3.1: {} @@ -1875,7 +1887,7 @@ snapshots: wrappy@1.0.2: {} - ws@8.18.1: {} + ws@8.18.2: {} xml-name-validator@5.0.0: {} diff --git a/backend/server.js b/backend/server.js index 33b1df6..115766e 100644 --- a/backend/server.js +++ b/backend/server.js @@ -2,6 +2,7 @@ const express = require("express"); const app = express(); +var cors = require('cors') const configManager = require("./src/utils/configManager"); const { connectDatabase, initDatabase } = require('./src/database/index'); @@ -12,6 +13,9 @@ const config = configManager.loadConfig(); // --- Body parsing --- app.use(express.json()); // Necessary to parse JSON bodies +// --- Cors --- +app.use(cors()); + // Database connection (async () => { diff --git a/frontend/src/app.jsx b/frontend/src/app.jsx index 7605b9e..5e1bbed 100644 --- a/frontend/src/app.jsx +++ b/frontend/src/app.jsx @@ -25,15 +25,15 @@ export function App() { return ( <> - + - + {/* */} - + {/* Here for nothing */} {/* +
+ This is a card ! + {item.name} +
) } -export default Button; \ No newline at end of file +export default GridCard; \ No newline at end of file diff --git a/frontend/src/components/Cards/grid.module.css b/frontend/src/components/Cards/grid.module.css index e69de29..0c009c5 100644 --- a/frontend/src/components/Cards/grid.module.css +++ b/frontend/src/components/Cards/grid.module.css @@ -0,0 +1,9 @@ +.gridCard { + + background-color: #3a3a3a; + border: #4a4a4a .1em solid; + + /* height: 10vh; */ + /* width: 10vw; */ +} + diff --git a/frontend/src/components/Cards/row.jsx b/frontend/src/components/Cards/row.jsx new file mode 100644 index 0000000..7955952 --- /dev/null +++ b/frontend/src/components/Cards/row.jsx @@ -0,0 +1,31 @@ +// Preact +import { h } from 'preact' // Necessary ? +// Components +import Button from '../Buttons/button' +// Styles +import styles from './row.module.css' +// Images +import Thumbnail from '../../assets/mod.svg' +import DownloadIcon from '../../assets/download_alt.svg' + +function GridCard({item}) { + return ( +
+ + + +

{item.description} +

+
+ {item.display_name} + By {item.author} +
+ +
+ ) +} + +export default GridCard; \ No newline at end of file diff --git a/frontend/src/components/Cards/row.module.css b/frontend/src/components/Cards/row.module.css new file mode 100644 index 0000000..a47ced0 --- /dev/null +++ b/frontend/src/components/Cards/row.module.css @@ -0,0 +1,76 @@ +.rowCard { + + height: 7rem; + margin-bottom: 1rem; + + background-color: #1a1a1a; + border: #3a3a3a .1rem solid; + border-radius: .5rem; +} + +.thumbnail { + position: absolute; + /* top: 1rem; */ + /* left: 1rem; */ + + margin: 0.93rem; + + height: 5rem; + width: 5rem; + + border: #3a3a3a .1rem solid; + border-radius: .5rem; +} + +.titleDiv { + margin-left: 7rem; + margin-top: 1rem; +} + +.title { + + margin: 3rem 0; + + font-size: 1.4rem; + font-weight: 600; +} + +.author { + /* left: 17rem; */ + + /* margin: 1rem 0; */ + color: #7a7a7a; +} + +.description { + position: absolute; + left: 7rem; + + margin: 3rem 0; + max-height: 10px; + + color: #939393; + /*TODO limit height*/ +} + +.downloadButton { + position: absolute; + /* top: 1rem; */ + right: 0; + + margin: 0.8rem; + + + /* height: 5rem; */ + /* width: 5rem; */ + + font-size: 1.1rem; + font-weight: 300; + border: #3a3a3a .1rem solid; + border-radius: .5rem; +} + +.downloadIcon { + margin-bottom: -.35rem; + margin-right: .3rem; +} \ No newline at end of file diff --git a/frontend/src/components/NavBar/navbar.jsx b/frontend/src/components/NavBar/navbar.jsx index 3511439..cf93e59 100644 --- a/frontend/src/components/NavBar/navbar.jsx +++ b/frontend/src/components/NavBar/navbar.jsx @@ -16,7 +16,7 @@ function NavBar({ children, className, ...rest}) { className={styles.navbar} {...rest} // Allow passing other props like 'disabled', 'type', etc. > - Home + Home Mods Modpacks About diff --git a/frontend/src/components/NavBar/navbar.module.css b/frontend/src/components/NavBar/navbar.module.css index 5f74bdf..c52752e 100644 --- a/frontend/src/components/NavBar/navbar.module.css +++ b/frontend/src/components/NavBar/navbar.module.css @@ -32,6 +32,8 @@ font-weight: 500; transition: 200ms; + + user-select: none; } .leftItem:hover { @@ -44,6 +46,8 @@ margin-right: 2em; margin-top: .3em; + user-select: none; + transition: 200ms; } diff --git a/frontend/src/main.jsx b/frontend/src/main.jsx index d5cd39c..7b7dea2 100644 --- a/frontend/src/main.jsx +++ b/frontend/src/main.jsx @@ -1,5 +1,4 @@ import { render } from 'preact' -import './styles/global.css' import { App } from './app.jsx' render(, document.getElementById('app')) diff --git a/frontend/src/pages/home.jsx b/frontend/src/pages/home.jsx index bb841c2..73db156 100644 --- a/frontend/src/pages/home.jsx +++ b/frontend/src/pages/home.jsx @@ -3,6 +3,7 @@ import { h } from 'preact'; // Images import logo from '../assets/logo.png' +import dl_icon from '../assets/download.svg' // Styles import '../styles/home.css' @@ -15,12 +16,12 @@ function HomePage() { return ( <> - +
- +
An open place for mods
- +
diff --git a/frontend/src/pages/mods.jsx b/frontend/src/pages/mods.jsx index a755afd..b081437 100644 --- a/frontend/src/pages/mods.jsx +++ b/frontend/src/pages/mods.jsx @@ -1,5 +1,9 @@ -// Functions +// Preact import { h } from 'preact'; +import { useState, useEffect } from 'preact/hooks'; + +// Functions +import { fetchMods } from '../services/api'; // Components import FiltersPanel from '../components/Filters/panel' @@ -9,19 +13,71 @@ import logo from '../assets/logo.png' // Styles import '../styles/mods.css' +import GridCard from '../components/Cards/grid'; +import RowCard from '../components/Cards/row'; function ModsPage() { - return ( - <> - + // UseState + const [mods, setMods] = useState([]); + const [loading, setLoading] = useState(true) + const [error, setError] = useState(null) + + // UseEffect + useEffect(() => { + async function loadItems() { + setLoading(true); + setError(false); + try { + const fetched_mods = await fetchMods(); + setMods(fetched_mods); + } catch (err) { + setError(err.message); + } finally { + setLoading(false); + } + } + + loadItems(); + }, []); // <-- Tells useEffect to run once after render + + if (loading) { + // TODO replace by loading screen + return
Loading mods
+ } + if (error) { + // TODO replace by popup + return
Couldn't load mods: {error}
+ } + + // Debugging + console.debug(mods); + const testArray = [(1, 'a'), (2, 'b'), (3, 'c')]; + + return ( + <> +
- +
-
- +
+ {/* Test card */} + {/* */} + + {mods.map((mod) => { + console.debug(mod.name); + // return
Test
+ return + })} + + {testArray.map((item, index) => { + // + console.debug(index, item) + })} +
+ ); } diff --git a/frontend/src/services/api.js b/frontend/src/services/api.js new file mode 100644 index 0000000..4b3352b --- /dev/null +++ b/frontend/src/services/api.js @@ -0,0 +1,15 @@ +const API_BASE_URL = 'http://localhost:8000'; + +export async function fetchMods() { + try { + const response = await fetch(`${API_BASE_URL}/list/mods`); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + const data = await response.json(); + return data; + } catch (error) { + console.error('Failed to fetch items:', error); + return []; + } +} \ No newline at end of file diff --git a/frontend/src/styles/app.css b/frontend/src/styles/app.css index 4914fc8..3af2410 100644 --- a/frontend/src/styles/app.css +++ b/frontend/src/styles/app.css @@ -1,3 +1,28 @@ +/* Impports */ +@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500&family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap'); + + +:root { + font-family: 'IBM Plex Mono'; + line-height: 1.5; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #0c0c0c; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +body { + min-width: 320px; + margin: 0; +} + + a { text-decoration: none; } @@ -9,22 +34,26 @@ a { top: 1.6rem; left: 2rem; height: 6em; + padding: 1.5em; + + user-select: none; } .logo.text { - position: relative; - left: 5rem; - top: 3.3rem; + position: absolute; + left: 10rem; + top: 3.8rem; + + margin: 0; color: #eaeaea; font-family: Inter; font-weight: 600; - - padding: 1.5em; - font-size: 3em; + + user-select: none; } h1 { @@ -53,10 +82,10 @@ h1 { min-height: 20rem; min-width: 50rem; - background-color: #1a1a1a; + /* background-color: #1a1a1a; */ color: #eaeaea; - border: #3a3a3a solid; + /* border: #3a3a3a solid; */ border-width: .1em; border-radius: .5rem; } diff --git a/frontend/src/styles/global.css b/frontend/src/styles/global.css deleted file mode 100644 index 67db913..0000000 --- a/frontend/src/styles/global.css +++ /dev/null @@ -1,22 +0,0 @@ -/* Impports */ -@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500&family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap'); - - -:root { - font-family: 'IBM Plex Mono'; - line-height: 1.5; - font-weight: 400; - - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: #0c0c0c; - - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -body { - min-width: 320px; -} diff --git a/frontend/src/styles/home.css b/frontend/src/styles/home.css index 7bf0622..80c9a0c 100644 --- a/frontend/src/styles/home.css +++ b/frontend/src/styles/home.css @@ -34,7 +34,7 @@ .start-button { position: fixed; - top: 38rem; + top: 48rem; left: 50%; transform: translate(-50%, -50%); /*Center (compensate size)*/ @@ -42,5 +42,4 @@ text-align: center; font-weight: 600; font-size: 2rem; - letter-spacing: 0.1rem; } \ No newline at end of file