diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c6325f0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +# Dependencies +node_modules/ + +# Build output (Cloudflare Pages builds this) +_site/ + +# Environment +.env +.env.local diff --git a/_data/tasks.js b/_data/tasks.js new file mode 100644 index 0000000..c93ac33 --- /dev/null +++ b/_data/tasks.js @@ -0,0 +1,128 @@ +const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args)); + +module.exports = async function() { + const GITEA_API = 'https://git.firefrostgaming.com/api/v1'; + const REPO_OWNER = 'firefrost-gaming'; + const REPO_NAME = 'firefrost-operations-manual'; + const TOKEN = process.env.GITEA_TOKEN || 'e0e330cba1749b01ab505093a160e4423ebbbe36'; + + const tasks = []; + + try { + // Get list of task directories + const response = await fetch( + `${GITEA_API}/repos/${REPO_OWNER}/${REPO_NAME}/contents/docs/tasks?ref=master`, + { + headers: { + 'Authorization': `token ${TOKEN}`, + 'Accept': 'application/json' + }, + timeout: 30000 + } + ); + + if (!response.ok) { + console.error('Failed to fetch task list:', response.status); + return []; + } + + const dirs = await response.json(); + const taskDirs = dirs.filter(d => d.type === 'dir' && d.name !== '_archive'); + + // Fetch each task's README + for (const dir of taskDirs) { + try { + // Try README.md first + let readmePath = `docs/tasks/${dir.name}/README.md`; + let readmeResponse = await fetch( + `${GITEA_API}/repos/${REPO_OWNER}/${REPO_NAME}/contents/${encodeURIComponent(readmePath)}?ref=master`, + { + headers: { + 'Authorization': `token ${TOKEN}`, + 'Accept': 'application/json' + } + } + ); + + if (!readmeResponse.ok) { + // Try to find any .md file + const filesResponse = await fetch( + `${GITEA_API}/repos/${REPO_OWNER}/${REPO_NAME}/contents/docs/tasks/${encodeURIComponent(dir.name)}?ref=master`, + { + headers: { + 'Authorization': `token ${TOKEN}`, + 'Accept': 'application/json' + } + } + ); + + if (filesResponse.ok) { + const files = await filesResponse.json(); + const mdFile = files.find(f => f.name.endsWith('.md')); + if (mdFile) { + readmePath = `docs/tasks/${dir.name}/${mdFile.name}`; + readmeResponse = await fetch( + `${GITEA_API}/repos/${REPO_OWNER}/${REPO_NAME}/contents/${encodeURIComponent(readmePath)}?ref=master`, + { + headers: { + 'Authorization': `token ${TOKEN}`, + 'Accept': 'application/json' + } + } + ); + } + } + } + + if (readmeResponse && readmeResponse.ok) { + const fileData = await readmeResponse.json(); + const content = Buffer.from(fileData.content, 'base64').toString('utf-8'); + + // Parse YAML frontmatter + const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/); + if (frontmatterMatch) { + const frontmatter = {}; + frontmatterMatch[1].split('\n').forEach(line => { + const match = line.match(/^(\w+):\s*(.+)$/); + if (match) { + frontmatter[match[1]] = match[2].trim(); + } + }); + + // Extract title from first H1 + const titleMatch = content.match(/^#\s+(.+)$/m); + const title = titleMatch ? titleMatch[1] : dir.name; + + tasks.push({ + slug: dir.name, + title: title, + status: frontmatter.status || 'open', + priority: frontmatter.priority || 'P3', + owner: frontmatter.owner || 'Michael', + created: frontmatter.created || '2026-01-01', + giteaUrl: `https://git.firefrostgaming.com/${REPO_OWNER}/${REPO_NAME}/src/branch/master/docs/tasks/${encodeURIComponent(dir.name)}` + }); + } + } + } catch (err) { + console.error(`Error processing ${dir.name}:`, err.message); + } + } + + // Sort by priority (P1 first) then by title + tasks.sort((a, b) => { + if (a.priority !== b.priority) { + return a.priority.localeCompare(b.priority); + } + return a.title.localeCompare(b.title); + }); + + console.log(`[11ty] Loaded ${tasks.length} tasks from Gitea`); + return tasks; + + } catch (err) { + console.error('[11ty] Error fetching tasks:', err.message); + // Return empty array - page will still build, just with no tasks + return []; + } +}; diff --git a/package-lock.json b/package-lock.json index a1b8b38..d1ee82e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,9 @@ "name": "firefrost-website", "version": "1.0.0", "license": "ISC", + "dependencies": { + "node-fetch": "^2.7.0" + }, "devDependencies": { "@11ty/eleventy": "^3.0.0" } @@ -1218,6 +1221,26 @@ "dev": true, "license": "MIT" }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/node-retrieve-globals": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/node-retrieve-globals/-/node-retrieve-globals-6.0.1.tgz", @@ -1603,6 +1626,12 @@ "node": ">=0.6" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, "node_modules/uc.micro": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", @@ -1627,6 +1656,22 @@ "dev": true, "license": "MIT" }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/ws": { "version": "8.20.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz", diff --git a/package.json b/package.json index 1a08f06..d0a9871 100644 --- a/package.json +++ b/package.json @@ -11,5 +11,8 @@ "license": "ISC", "devDependencies": { "@11ty/eleventy": "^3.0.0" + }, + "dependencies": { + "node-fetch": "^2.7.0" } } diff --git a/tasks-index.njk b/tasks-index.njk new file mode 100644 index 0000000..783ed21 --- /dev/null +++ b/tasks-index.njk @@ -0,0 +1,263 @@ +--- +layout: false +permalink: /tasks-index.html +--- + + + + + + Tasks - Firefrost Gaming + + + +
+

🔥 Firefrost Tasks ❄️

+
+ +
+
+ +
+ + + + + +
+ +
+ {% for task in tasks %} + {% if task.status == "open" or task.status == "blocked" %} +
+
+ + {{ task.priority }} +
+
+ {{ task.owner }} + {{ task.created }} + {% if task.status == "blocked" %} + ⚠️ BLOCKED + {% endif %} +
+
+ {% endif %} + {% endfor %} +
+ + + + + +