Add a real submission form, bypassing the broken Gitea issue-template render
Build and validate / build (push) Successful in 11s

Gitea 1.27.1 on this instance silently ignores the ?template= param for
.github/ISSUE_TEMPLATE/hardware-report.yml — the structured fields never
render, just a blank title/body editor (confirmed live: same URL that's
supposed to load the form shows nothing). Rather than debug Gitea's YAML
issue-forms support, site/report.html is a plain form matching the schema
that builds a title + markdown body (with a ready-to-merge YAML block) and
opens Gitea's issues/new with them pre-filled via query params, which does
work on this instance (verified live).

Verified the full round trip in a real browser: filled the form, submitted,
confirmed the opened Gitea tab has the correct title and a body containing
valid YAML matching every field. Did not actually click "Create Issue" —
no reason to leave a test issue on the tracker.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-03 22:37:27 +00:00
co-authored by Claude Sonnet 5
parent f188fe562f
commit c8f6102cfd
5 changed files with 313 additions and 6 deletions
+10 -4
View File
@@ -2,11 +2,17 @@
Two ways to add a report, pick whichever's easier for you.
## Option A — open an issue (no git needed)
## Option A — use the report form (no git needed)
[Open a hardware report issue](https://source.archipelago-foundation.org/ssmithx/ArchyHCL/issues/new?template=hardware-report.yml)
and fill in the form. A maintainer will turn it into a data file and it'll
show up on the site.
[Fill in the report form](https://hcl.archipelago-foundation.org/report.html) —
it opens a pre-filled Gitea issue with a ready-to-merge YAML block for you
(you'll still need a free Gitea account to post it). A maintainer copies the
block into a new data file and it shows up on the site.
(The repo's `.github/ISSUE_TEMPLATE/hardware-report.yml` structured issue
form doesn't render on this Gitea instance — it silently falls back to a
blank issue instead of showing the fields — so the site form above is the
supported no-git path, not the raw "New Issue" button.)
## Option B — open a PR directly
+2 -2
View File
@@ -8,10 +8,10 @@
</head>
<body>
<header>
<h1>ArchyHCL</h1>
<h1><a href="index.html">ArchyHCL</a></h1>
<p>Community-reported hardware compatibility for <a href="https://source.archipelago-foundation.org/lfg2025/archy" target="_blank" rel="noopener">Archipelago</a>. Every row here is a real install someone tested and reported — see it on GitHub/Gitea as a plain data file, no login required to browse.</p>
<p class="cta">
Tested Archipelago on your own hardware? <a href="https://source.archipelago-foundation.org/ssmithx/ArchyHCL/issues/new?template=hardware-report.yml" target="_blank" rel="noopener">Report it</a> —
Tested Archipelago on your own hardware? <a href="report.html">Report it</a> —
takes two minutes and helps the next person know what to expect before they buy or repurpose a machine.
</p>
</header>
+126
View File
@@ -0,0 +1,126 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Report hardware — ArchyHCL</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<h1><a href="index.html">ArchyHCL</a></h1>
<p>Fill this in, hit submit — it opens a pre-filled issue on Gitea with everything formatted and ready for a maintainer to merge. You'll still need a (free) Gitea account to actually post it.</p>
</header>
<main>
<form id="report-form" class="report-form">
<div class="field">
<label for="device_model">Device model *</label>
<input id="device_model" required placeholder="Lenovo ThinkPad T430">
</div>
<div class="field">
<label for="form_factor">Form factor *</label>
<select id="form_factor" required>
<option value="laptop">Laptop</option>
<option value="desktop">Desktop</option>
<option value="mini-pc">Mini PC</option>
<option value="sbc">SBC</option>
<option value="server">Server</option>
<option value="other">Other</option>
</select>
</div>
<div class="field">
<label for="cpu">CPU *</label>
<input id="cpu" required placeholder="Intel Core i5-3320M">
</div>
<div class="field-row">
<div class="field">
<label for="ram_gb">RAM (GB) *</label>
<input id="ram_gb" type="number" min="1" step="1" required placeholder="8">
</div>
<div class="field">
<label for="storage_type">Storage type *</label>
<select id="storage_type" required>
<option value="ssd">SSD</option>
<option value="nvme">NVMe</option>
<option value="hdd">HDD</option>
<option value="emmc">eMMC</option>
<option value="sd">SD card</option>
</select>
</div>
<div class="field">
<label for="storage_size_gb">Storage size (GB) *</label>
<input id="storage_size_gb" type="number" min="1" step="1" required placeholder="256">
</div>
</div>
<div class="field">
<label for="wifi_chip">WiFi chip *</label>
<input id="wifi_chip" required placeholder="Intel Centrino Advanced-N 6205 (or \"none\" if wired-only)">
</div>
<div class="field">
<label for="ethernet">Ethernet chip (optional)</label>
<input id="ethernet" placeholder="Intel 82579LM">
</div>
<div class="field-row">
<div class="field">
<label for="archy_version">Archipelago version tested *</label>
<input id="archy_version" required placeholder="1.8.4-alpha">
</div>
<div class="field">
<label for="install_method">Install method *</label>
<select id="install_method" required>
<option value="usb-iso">USB ISO</option>
<option value="netboot">Netboot</option>
<option value="existing-os-script">Existing-OS script</option>
<option value="other">Other</option>
</select>
</div>
<div class="field">
<label for="tested_date">Date tested *</label>
<input id="tested_date" type="date" required>
</div>
</div>
<div class="field">
<label for="status">Status *</label>
<select id="status" required>
<option value="working">Working — no known issues</option>
<option value="partial">Partial — runs, with specific known issues</option>
<option value="broken">Broken — does not install or run</option>
</select>
</div>
<div class="field">
<label for="issues">Issues <span id="issues-required" class="required-hint" hidden>(required for partial/broken)</span></label>
<textarea id="issues" rows="4" placeholder="What broke, and how you noticed. Include any workaround you found."></textarea>
</div>
<div class="field">
<label for="notes">Other notes (optional)</label>
<textarea id="notes" rows="3" placeholder="BIOS/UEFI settings needed, quirks, links to a fuller writeup."></textarea>
</div>
<div class="field">
<label for="submitted_by">Attribution (optional)</label>
<input id="submitted_by" placeholder="Your npub, Gitea username, or leave blank">
</div>
<p id="form-error" class="form-error" hidden></p>
<button type="submit">Open pre-filled issue on Gitea →</button>
</form>
</main>
<footer>
<p>Prefer git? See <a href="https://source.archipelago-foundation.org/ssmithx/ArchyHCL/src/branch/main/CONTRIBUTING.md" target="_blank" rel="noopener">CONTRIBUTING.md</a> for opening a PR directly instead.</p>
</footer>
<script src="report.js"></script>
</body>
</html>
+96
View File
@@ -0,0 +1,96 @@
// Builds a pre-filled Gitea "new issue" URL (title + body via query params —
// verified working on this Gitea instance even though its YAML issue-forms
// rendering (.github/ISSUE_TEMPLATE/hardware-report.yml) does not render as
// a structured form: it silently falls back to a blank issue instead, so we
// don't rely on it) and opens it. The body includes a ready-to-paste YAML
// block matching data/schema.json, so a maintainer can copy it straight
// into a new data/reports/*.yml file with minimal editing.
const REPO_URL = "https://source.archipelago-foundation.org/ssmithx/ArchyHCL";
const form = document.getElementById("report-form");
const statusSelect = document.getElementById("status");
const issuesField = document.getElementById("issues");
const issuesRequiredHint = document.getElementById("issues-required");
const errorEl = document.getElementById("form-error");
function updateIssuesRequirement() {
const required = statusSelect.value !== "working";
issuesRequiredHint.hidden = !required;
issuesField.required = required;
}
statusSelect.addEventListener("change", updateIssuesRequirement);
updateIssuesRequirement();
// A YAML double-quoted scalar uses the same escaping rules as JSON strings
// for every character that matters here (quotes, backslashes, control
// chars) — JSON.stringify is a safe, simple way to produce one.
function yamlString(value) {
return JSON.stringify(value ?? "");
}
function yamlBlock(value) {
const trimmed = (value ?? "").trim();
if (!trimmed) return null;
return trimmed
.split("\n")
.map((line) => " " + line)
.join("\n");
}
function val(id) {
return document.getElementById(id).value.trim();
}
function buildYaml() {
const lines = [];
lines.push(`device_model: ${yamlString(val("device_model"))}`);
lines.push(`form_factor: ${val("form_factor")}`);
lines.push(`cpu: ${yamlString(val("cpu"))}`);
lines.push(`ram_gb: ${val("ram_gb")}`);
lines.push("storage:");
lines.push(` type: ${val("storage_type")}`);
lines.push(` size_gb: ${val("storage_size_gb")}`);
lines.push(`wifi_chip: ${yamlString(val("wifi_chip"))}`);
const ethernet = val("ethernet");
if (ethernet) lines.push(`ethernet: ${yamlString(ethernet)}`);
lines.push(`archy_version: ${yamlString(val("archy_version"))}`);
lines.push(`install_method: ${val("install_method")}`);
lines.push(`status: ${val("status")}`);
lines.push(`tested_date: ${yamlString(val("tested_date"))}`);
const submittedBy = val("submitted_by");
if (submittedBy) lines.push(`submitted_by: ${yamlString(submittedBy)}`);
const issuesBlock = yamlBlock(val("issues"));
if (issuesBlock) lines.push(`issues: |\n${issuesBlock}`);
const notesBlock = yamlBlock(val("notes"));
if (notesBlock) lines.push(`notes: |\n${notesBlock}`);
return lines.join("\n");
}
form.addEventListener("submit", (e) => {
e.preventDefault();
errorEl.hidden = true;
if (statusSelect.value !== "working" && !val("issues")) {
errorEl.textContent = 'Please describe the issue(s) — required when status is "partial" or "broken".';
errorEl.hidden = false;
issuesField.focus();
return;
}
const deviceModel = val("device_model");
const title = `hw: ${deviceModel}`;
const yaml = buildYaml();
const body = [
`Hardware report for **${deviceModel}**, submitted via the site form.`,
"",
"A maintainer: copy the block below into a new file under `data/reports/` (see CONTRIBUTING.md) to add it to the list.",
"",
"```yaml",
yaml,
"```",
].join("\n");
const url = `${REPO_URL}/issues/new?title=${encodeURIComponent(title)}&body=${encodeURIComponent(body)}`;
window.open(url, "_blank", "noopener");
});
+79
View File
@@ -138,3 +138,82 @@ footer code {
padding: 0.1rem 0.35rem;
border-radius: 3px;
}
h1 a { color: inherit; text-decoration: none; }
h1 a:hover { color: var(--accent); }
.report-form {
display: flex;
flex-direction: column;
gap: 1rem;
max-width: 640px;
}
.field {
display: flex;
flex-direction: column;
gap: 0.3rem;
flex: 1;
}
.field-row {
display: flex;
gap: 1rem;
flex-wrap: wrap;
}
.field-row .field {
min-width: 140px;
}
label {
color: var(--muted);
font-size: 0.85rem;
}
.required-hint {
color: var(--partial);
font-weight: normal;
}
textarea {
background: var(--panel);
border: 1px solid var(--border);
color: var(--text);
padding: 0.5rem 0.7rem;
border-radius: 4px;
font-family: inherit;
font-size: 0.9rem;
resize: vertical;
}
textarea:focus, .report-form input:focus, .report-form select:focus {
outline: none;
border-color: var(--accent-dim);
}
.report-form input, .report-form select {
width: 100%;
}
.form-error {
color: var(--broken);
font-size: 0.85rem;
}
.report-form button {
align-self: flex-start;
background: var(--accent);
color: var(--bg);
border: none;
padding: 0.7rem 1.2rem;
border-radius: 4px;
font-family: inherit;
font-weight: bold;
font-size: 0.9rem;
cursor: pointer;
}
.report-form button:hover {
background: var(--accent-dim);
}