landing updates
All checks were successful
Apply Kuberentes Configs / update-repo (push) Successful in 1s
Apply Kuberentes Configs / update-infrastructure (push) Successful in 4s
Apply Kuberentes Configs / notify-on-failure (push) Has been skipped
Manage Jellyfin Playlists / update-repo (push) Successful in 1s
Libation / update-repo (push) Successful in 0s
Libation / sync-audiobooks (push) Successful in 5s
Libation / notify-on-failure (push) Has been skipped
Manage Jellyfin Playlists / run-python (push) Successful in 47s
Manage Jellyfin Playlists / notify-on-failure (push) Has been skipped

This commit is contained in:
2026-03-05 10:59:46 -07:00
parent ee5966306a
commit ceb89d92fe
2 changed files with 35 additions and 15 deletions

View File

@@ -46,6 +46,6 @@
window.GITEA_SUB_URL = "{{AppSubUrl}}"; window.GITEA_SUB_URL = "{{AppSubUrl}}";
</script> </script>
<!-- update version when changed to reset cloudflare cache --> <!-- update version when changed to reset cloudflare cache -->
<script src="{{AppSubUrl}}/assets/js/custom-landing.js?v=8"></script> <script src="{{AppSubUrl}}/assets/js/custom-landing.js?v=9"></script>
<link href="{{AppSubUrl}}/assets/css/custom-landing.css?v=8" rel="stylesheet" /> <link href="{{AppSubUrl}}/assets/css/custom-landing.css?v=9" rel="stylesheet" />
{{template "base/footer" .}} {{template "base/footer" .}}

View File

@@ -1,12 +1,18 @@
const baseUrl = window.GITEA_SUB_URL || "";
const httpService = { const httpService = {
baseUrl: window.GITEA_SUB_URL || "",
async fetchRss() { async fetchRss() {
const resp = await fetch(`${this.baseUrl}/alex.rss`); const resp = await fetch(`${baseUrl}/alex.rss`);
if (!resp.ok) throw new Error(`HTTP ${resp.status}`); if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
const text = await resp.text(); const text = await resp.text();
return new DOMParser().parseFromString(text, "application/xml"); return new DOMParser().parseFromString(text, "application/xml");
}, },
async fetchHeatmap(username = "alex") {
const resp = await fetch(`${baseUrl}/api/v1/users/${username}/heatmap`);
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
return resp.json(); // [{timestamp: unix_seconds, contributions: number}]
},
}; };
const dataDomain = { const dataDomain = {
@@ -94,7 +100,7 @@ const dataDomain = {
: repoName, : repoName,
pubDate: item.querySelector("pubDate")?.textContent || "", pubDate: item.querySelector("pubDate")?.textContent || "",
firstCommit: firstCommit:
this.parseCommits( dataDomain.parseCommits(
item.querySelector("description")?.textContent || "", item.querySelector("description")?.textContent || "",
)[0] || null, )[0] || null,
}); });
@@ -120,14 +126,14 @@ const dataDomain = {
.slice(0, limit) .slice(0, limit)
.map((item) => { .map((item) => {
const rawTitle = item.querySelector("title")?.textContent || ""; const rawTitle = item.querySelector("title")?.textContent || "";
const titleText = this.titlePlainText(rawTitle); const titleText = dataDomain.titlePlainText(rawTitle);
return { return {
titleHtmlSafe: this.safeTitleHtml(rawTitle), titleHtmlSafe: dataDomain.safeTitleHtml(rawTitle),
titleText, titleText,
link: item.querySelector("link")?.textContent || "#", link: item.querySelector("link")?.textContent || "#",
pubDate: item.querySelector("pubDate")?.textContent || "", pubDate: item.querySelector("pubDate")?.textContent || "",
icon: this.activityIcon(titleText), icon: dataDomain.activityIcon(titleText),
commits: this.parseCommits( commits: dataDomain.parseCommits(
item.querySelector("description")?.textContent || "", item.querySelector("description")?.textContent || "",
).slice(0, 3), ).slice(0, 3),
}; };
@@ -221,11 +227,25 @@ const uiRendering = {
} }
}, },
activityMapRender(xmlDoc) { async activityMapRender() {
const container = document.getElementById("activity-heatmap"); const container = document.getElementById("activity-heatmap");
if (!container) return; if (!container) return;
const counts = dataDomain.parseAllActivityDates(xmlDoc); let heatmapData;
try {
heatmapData = await httpService.fetchHeatmap();
} catch (e) {
container.innerHTML = `<div class="error-msg">Could not load heatmap (${e.message})</div>`;
return;
}
// Build counts map from API data
const counts = new Map();
for (const { timestamp, contributions } of heatmapData) {
const d = new Date(timestamp * 1000);
const key = d.toISOString().slice(0, 10);
counts.set(key, (counts.get(key) || 0) + (contributions || 1));
}
const today = new Date(); const today = new Date();
today.setHours(0, 0, 0, 0); today.setHours(0, 0, 0, 0);
@@ -245,7 +265,7 @@ const uiRendering = {
const svgW = padLeft + cols * step; const svgW = padLeft + cols * step;
const svgH = padTop + rows * step; const svgH = padTop + rows * step;
const LEVELS = ["#161b22", "#0e4429", "#006d32", "#26a641", "#39d353"]; const LEVELS = ["#2d333b", "#0e4429", "#006d32", "#26a641", "#39d353"];
const countToLevel = (n) => const countToLevel = (n) =>
n === 0 ? 0 : n === 1 ? 1 : n <= 3 ? 2 : n <= 6 ? 3 : 4; n === 0 ? 0 : n === 1 ? 1 : n <= 3 ? 2 : n <= 6 ? 3 : 4;
@@ -356,9 +376,9 @@ const uiRendering = {
try { try {
const xmlDoc = await httpService.fetchRss(); const xmlDoc = await httpService.fetchRss();
await Promise.all([ await Promise.all([
this.renderRepos(xmlDoc), uiRendering.renderRepos(xmlDoc),
this.renderActivity(xmlDoc), uiRendering.renderActivity(xmlDoc),
this.activityMapRender(xmlDoc), uiRendering.activityMapRender(),
]); ]);
} catch (e) { } catch (e) {
console.error("Gitea landing: RSS fetch failed", e); console.error("Gitea landing: RSS fetch failed", e);