side: /now m. git-aktivitets-heatmap fra egen Gitea (build-time)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
02dacf32da
commit
c21974a3ce
@@ -0,0 +1,82 @@
|
||||
---
|
||||
import Base from '../layouts/Base.astro';
|
||||
import { SITE } from '../consts';
|
||||
|
||||
// Hvad jeg roder med lige nu — opdateres manuelt, det er hele pointen med en /now-side.
|
||||
const focus = [
|
||||
'Elektronisk fakturering hos Digisense: Peppol, NemHandel og løsningsarkitektur',
|
||||
'HD 1. del i Erhvervsøkonomi på AAU (eksamener til sommer)',
|
||||
'Homelab: crawlkit, denne side, og alt for mange LXC-containere',
|
||||
];
|
||||
|
||||
// Build-time: aktivitets-heatmap fra min Gitea (offentligt API). Fejler stille —
|
||||
// siden bygger fint uden graf hvis Gitea er nede under build.
|
||||
type Beat = { timestamp: number; contributions: number };
|
||||
let perDay = new Map<string, number>();
|
||||
try {
|
||||
const r = await fetch(`${SITE.giteaBase}/api/v1/users/${SITE.giteaUser}/heatmap`);
|
||||
if (r.ok) for (const b of (await r.json()) as Beat[]) {
|
||||
const d = new Date(b.timestamp * 1000).toISOString().slice(0, 10);
|
||||
perDay.set(d, (perDay.get(d) || 0) + b.contributions);
|
||||
}
|
||||
} catch { /* ingen graf, ingen drama */ }
|
||||
|
||||
// 26 uger bagud, uger som kolonner (man-søn), niveau 0-4
|
||||
const WEEKS = 26;
|
||||
const today = new Date(); today.setHours(12, 0, 0, 0);
|
||||
const start = new Date(today); start.setDate(start.getDate() - (WEEKS * 7 - 1) - ((today.getDay() + 6) % 7));
|
||||
const weeks: { date: string; n: number }[][] = [];
|
||||
const cur = new Date(start);
|
||||
while (cur <= today) {
|
||||
const week: { date: string; n: number }[] = [];
|
||||
for (let i = 0; i < 7 && cur <= today; i++) {
|
||||
const key = cur.toISOString().slice(0, 10);
|
||||
week.push({ date: key, n: perDay.get(key) || 0 });
|
||||
cur.setDate(cur.getDate() + 1);
|
||||
}
|
||||
weeks.push(week);
|
||||
}
|
||||
const level = (n: number) => (n === 0 ? 0 : n < 3 ? 1 : n < 6 ? 2 : n < 12 ? 3 : 4);
|
||||
const total = [...perDay.values()].reduce((a, b) => a + b, 0);
|
||||
const updated = today.toLocaleDateString('da-DK', { year: 'numeric', month: 'long', day: 'numeric' });
|
||||
---
|
||||
<Base title="Now" description="Hvad jeg arbejder på lige nu — plus et aktivitets-heatmap fra min self-hostede Gitea.">
|
||||
<h1 class="text-4xl font-bold tracking-tight">Now</h1>
|
||||
<p class="mt-2 text-sm text-muted">Senest opdateret {updated} · à la <a class="text-accent hover:underline" href="https://nownownow.com/about" target="_blank" rel="noopener">nownownow.com</a></p>
|
||||
|
||||
<section class="mt-8">
|
||||
<h2 class="text-sm font-semibold uppercase tracking-widest text-accent">Lige nu</h2>
|
||||
<ul class="mt-4 space-y-3">
|
||||
{focus.map((f) => (
|
||||
<li class="rounded-2xl border border-border bg-surface/60 p-4 text-sm">{f}</li>
|
||||
))}
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
{weeks.length > 0 && (
|
||||
<section class="mt-10">
|
||||
<h2 class="text-sm font-semibold uppercase tracking-widest text-accent">Git-aktivitet</h2>
|
||||
<p class="mt-2 text-sm text-muted">{total} bidrag i mit eget Gitea det seneste år — de seneste {WEEKS} uger:</p>
|
||||
<div class="mt-4 overflow-x-auto rounded-2xl border border-border bg-surface/60 p-4">
|
||||
<div class="heatmap" role="img" aria-label="Aktivitets-heatmap over git-bidrag">
|
||||
{weeks.map((w) => (
|
||||
<div class="hm-col">
|
||||
{w.map((d) => <span class={`hm-cell hm-${level(d.n)}`} title={`${d.date}: ${d.n} bidrag`} />)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<p class="mt-2 text-xs text-muted/80">Offentlige projekter ligger på <a class="text-accent hover:underline" href={`${SITE.giteaBase}/${SITE.giteaUser}`} target="_blank" rel="noopener">gitea.weircon.dk</a>.</p>
|
||||
</section>
|
||||
)}
|
||||
|
||||
<style>
|
||||
.heatmap { display: flex; gap: 3px; width: max-content; }
|
||||
.hm-col { display: flex; flex-direction: column; gap: 3px; }
|
||||
.hm-cell { width: 11px; height: 11px; border-radius: 2.5px; background: var(--color-surface-2); }
|
||||
.hm-1 { background: color-mix(in srgb, var(--color-accent) 30%, var(--color-surface-2)); }
|
||||
.hm-2 { background: color-mix(in srgb, var(--color-accent) 55%, var(--color-surface-2)); }
|
||||
.hm-3 { background: color-mix(in srgb, var(--color-accent) 80%, var(--color-surface-2)); }
|
||||
.hm-4 { background: var(--color-accent); }
|
||||
</style>
|
||||
</Base>
|
||||
Reference in New Issue
Block a user