feat(render): card owner pill + short ISO date span

closes board-viewer-card-meta-fix

Review found two acceptance fields missing from cards:
- project_owner was in JSON but never displayed
- last_commit_iso was only consumed for relative age; no absolute date

Now both rendered (server-side src/render.ts + client-side static/board.js
in sync), with 4 new TDD tests:
- renders owner pill when project_owner is set
- omits owner pill when empty
- renders short YYYY-MM-DD date when last_commit_iso is set
- omits date span when null

CSS: .badge.owner = transparent + border (visually distinct from solid
.badge.project), .date = small muted tabular-nums. Smoke-verified in browser.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
vitya
2026-05-22 15:42:59 +03:00
parent 7cebeda219
commit 930e404545
6 changed files with 79 additions and 7 deletions

View File

@@ -117,15 +117,27 @@ function renderCard(r: TaskRecord, now: Date, archiveDays: number): string {
const age = formatAge(r.last_commit_iso, now);
const archived = r.status === 'done' && isOlderThanDays(r.last_commit_iso, now, archiveDays);
const truncatedTitle = truncate(r.title, TITLE_MAX);
const ownerPill = r.project_owner
? `<span class="badge owner">${escapeHtml(r.project_owner)}</span>`
: '';
const dateSpan = r.last_commit_iso
? `<span class="date" title="${attr(r.last_commit_iso)}">${escapeHtml(shortDate(r.last_commit_iso))}</span>`
: '';
return ` <li class="card" data-slug="${attr(r.slug)}" data-raw-url="${attr(r.raw_url)}" data-archived="${archived ? 'true' : 'false'}">
<div class="card-title">${escapeHtml(truncatedTitle)}</div>
<div class="card-meta">
<span class="badge project">${escapeHtml(r.project)}</span>
${ownerPill}
${dateSpan}
${age === null ? '' : `<span class="age">${escapeHtml(age)}</span>`}
</div>
</li>`;
}
function shortDate(iso: string): string {
return iso.slice(0, 10);
}
function isOlderThanDays(iso: string | null, now: Date, days: number): boolean {
if (iso === null) return false;
const diffMs = now.getTime() - new Date(iso).getTime();