mirror of
https://github.com/praktimarc/kst4contest.git
synced 2026-07-13 16:16:44 +02:00
Website Build with Roadmap.
This commit is contained in:
@@ -4,6 +4,7 @@ module.exports = [
|
||||
{ title: "Screenshots", url: "/screenshots/" },
|
||||
{ title: "Manual", url: "/manual/" },
|
||||
{ title: "News", url: "/news/" },
|
||||
{ title: "Roadmap", url: "/roadmap/" },
|
||||
{ title: "About", url: "/about/" },
|
||||
{ title: "FAQ", url: "/faq/" }
|
||||
];
|
||||
@@ -0,0 +1,84 @@
|
||||
const REPO = "praktimarc/kst4contest";
|
||||
const API = `https://api.github.com/repos/${REPO}`;
|
||||
|
||||
async function githubGet(path) {
|
||||
const headers = { Accept: "application/vnd.github+json" };
|
||||
if (process.env.GITHUB_TOKEN) {
|
||||
headers.Authorization = `Bearer ${process.env.GITHUB_TOKEN}`;
|
||||
}
|
||||
const res = await fetch(`${API}${path}`, { headers });
|
||||
if (!res.ok) {
|
||||
throw new Error(`GitHub API ${path} failed: ${res.status}`);
|
||||
}
|
||||
return res.json();
|
||||
}
|
||||
|
||||
// Builds the roadmap from all GitHub issues tagged "enhancement", grouped by
|
||||
// their version milestone (open or already released). Issues without a
|
||||
// milestone are shown as planned but with no assigned version yet. Issues
|
||||
// closed as "not planned" are kept, struck through and labeled accordingly.
|
||||
// Falls back to an empty list if the API is unreachable (e.g. offline build)
|
||||
// so the site build never fails.
|
||||
module.exports = async function () {
|
||||
try {
|
||||
const issues = await githubGet(
|
||||
"/issues?labels=enhancement&state=all&per_page=100"
|
||||
);
|
||||
|
||||
const groups = new Map();
|
||||
|
||||
for (const issue of issues) {
|
||||
if (issue.pull_request) continue;
|
||||
|
||||
const milestone = issue.milestone;
|
||||
const key = milestone ? milestone.number : "unscheduled";
|
||||
|
||||
if (!groups.has(key)) {
|
||||
groups.set(key, {
|
||||
version: milestone ? milestone.title : null,
|
||||
description: milestone ? milestone.description : null,
|
||||
url: milestone ? milestone.html_url : null,
|
||||
released: milestone ? milestone.state === "closed" : false,
|
||||
dueOn: milestone && milestone.due_on ? new Date(milestone.due_on) : null,
|
||||
releasedOn: milestone && milestone.closed_at ? new Date(milestone.closed_at) : null,
|
||||
enhancements: []
|
||||
});
|
||||
}
|
||||
|
||||
const notPlanned = issue.state === "closed" && issue.state_reason === "not_planned";
|
||||
|
||||
groups.get(key).enhancements.push({
|
||||
title: issue.title,
|
||||
url: issue.html_url,
|
||||
done: issue.state === "closed" && !notPlanned,
|
||||
notPlanned
|
||||
});
|
||||
}
|
||||
|
||||
const versions = [...groups.values()].filter((v) => v.enhancements.length > 0);
|
||||
|
||||
// Order: upcoming dated versions first (soonest due date), then
|
||||
// upcoming undated versions, then already released versions (newest
|
||||
// first), unscheduled enhancements at the very end.
|
||||
versions.sort((a, b) => {
|
||||
if (!a.version) return 1;
|
||||
if (!b.version) return -1;
|
||||
if (a.released !== b.released) return a.released ? 1 : -1;
|
||||
|
||||
if (!a.released) {
|
||||
if (a.dueOn && b.dueOn) return a.dueOn - b.dueOn;
|
||||
if (a.dueOn) return -1;
|
||||
if (b.dueOn) return 1;
|
||||
return a.version.localeCompare(b.version);
|
||||
}
|
||||
|
||||
if (a.releasedOn && b.releasedOn) return b.releasedOn - a.releasedOn;
|
||||
return b.version.localeCompare(a.version);
|
||||
});
|
||||
|
||||
return versions;
|
||||
} catch (err) {
|
||||
console.warn(`[roadmap] Could not load GitHub issues: ${err.message}`);
|
||||
return [];
|
||||
}
|
||||
};
|
||||
@@ -415,6 +415,11 @@ a:hover {
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.roadmap-done a {
|
||||
color: var(--muted);
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.feature-icon {
|
||||
font-size: 2rem;
|
||||
margin-bottom: 14px;
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
---
|
||||
layout: base.njk
|
||||
title: KST4Contest Roadmap
|
||||
description: Planned enhancements for upcoming KST4Contest versions, generated from GitHub milestones and issues.
|
||||
---
|
||||
|
||||
<section class="hero">
|
||||
<p class="badge">Roadmap</p>
|
||||
<h1>What's planned next.</h1>
|
||||
<p class="lead">
|
||||
Generated automatically from the "enhancement" issues in our
|
||||
<a href="https://github.com/praktimarc/kst4contest">GitHub repository</a>,
|
||||
grouped by their target version milestone.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="section narrow">
|
||||
{% if roadmap.length == 0 %}
|
||||
<article class="card content-card">
|
||||
<p>No planned enhancements are currently assigned to a version milestone.</p>
|
||||
<p>
|
||||
See all open feature requests on
|
||||
<a href="https://github.com/praktimarc/kst4contest/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement">GitHub</a>.
|
||||
</p>
|
||||
</article>
|
||||
{% endif %}
|
||||
|
||||
{% for version in roadmap %}
|
||||
<article class="card content-card">
|
||||
{% if version.version %}
|
||||
<h2><a href="{{ version.url }}">{{ version.version }}</a></h2>
|
||||
{% else %}
|
||||
<h2>Planned, no version yet</h2>
|
||||
{% endif %}
|
||||
{% if version.description %}<p>{{ version.description }}</p>{% endif %}
|
||||
{% if version.released %}
|
||||
<p class="eyebrow">Released{% if version.releasedOn %} {{ version.releasedOn | readableDate }}{% endif %}</p>
|
||||
{% elif version.dueOn %}
|
||||
<p class="eyebrow">Due {{ version.dueOn | readableDate }}</p>
|
||||
{% endif %}
|
||||
<ul>
|
||||
{% for item in version.enhancements %}
|
||||
<li{% if item.done or item.notPlanned %} class="roadmap-done"{% endif %}>
|
||||
<a href="{{ item.url }}">{{ item.title }}</a>{% if item.done %} ✓{% endif %}{% if item.notPlanned %} (not planned){% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</article>
|
||||
{% endfor %}
|
||||
</section>
|
||||
Reference in New Issue
Block a user