Show related drafts in author cluster cards

Each cluster card now shows draft count badge and up to 5 linked draft
titles with clickable links to draft detail pages. Data collected from
member nodes' draft lists during cluster detection.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-07 21:23:13 +01:00
parent 34c36f81f1
commit 02049c37a8
2 changed files with 24 additions and 2 deletions

View File

@@ -572,15 +572,22 @@ def get_author_network_full(db: Database) -> dict:
if len(component) >= 2:
org_mix: dict[str, int] = Counter()
cluster_drafts: dict[str, str] = {} # name -> title
for m in component:
org = author_info.get(m, {}).get("org", "")
if org:
org_mix[org] += 1
for dn in author_info.get(m, {}).get("drafts", []):
if dn not in cluster_drafts:
d = db.get_draft(dn)
cluster_drafts[dn] = d.title[:80] if d else dn
clusters.append({
"id": len(clusters),
"members": component,
"org_mix": dict(org_mix.most_common()),
"size": len(component),
"drafts": [{"name": n, "title": t} for n, t in list(cluster_drafts.items())[:15]],
"draft_count": len(cluster_drafts),
})
clusters.sort(key=lambda c: c["size"], reverse=True)

View File

@@ -118,16 +118,31 @@
<div class="cluster-card bg-slate-800/50 rounded-lg border border-slate-700/50 p-4 cursor-pointer" data-cluster-id="{{ c.id }}" onclick="highlightCluster({{ c.id }})">
<div class="flex items-center justify-between mb-2">
<span class="text-sm font-semibold text-white">Cluster #{{ c.id + 1 }}</span>
<div class="flex gap-1.5">
<span class="text-xs px-2 py-0.5 rounded-full bg-blue-500/20 text-blue-400">{{ c.size }} authors</span>
<span class="text-xs px-2 py-0.5 rounded-full bg-emerald-500/20 text-emerald-400">{{ c.draft_count }} drafts</span>
</div>
</div>
<div class="flex flex-wrap gap-1 mb-2">
{% for org, count in c.org_mix.items() %}
<span class="text-xs px-2 py-0.5 rounded-full bg-slate-700 text-slate-300">{{ org }} ({{ count }})</span>
{% endfor %}
</div>
<div class="text-xs text-slate-500 truncate" title="{{ c.members | join(', ') }}">
<div class="text-xs text-slate-500 mb-2 truncate" title="{{ c.members | join(', ') }}">
{{ c.members[:5] | join(', ') }}{% if c.members | length > 5 %} +{{ c.members | length - 5 }} more{% endif %}
</div>
{% if c.drafts %}
<div class="border-t border-slate-700/50 pt-2 mt-2">
{% for d in c.drafts[:5] %}
<div class="text-xs truncate mb-0.5" title="{{ d.name }}: {{ d.title }}">
<a href="/drafts/{{ d.name }}" class="text-blue-400/70 hover:text-blue-300 transition" onclick="event.stopPropagation()">{{ d.title }}</a>
</div>
{% endfor %}
{% if c.draft_count > 5 %}
<div class="text-xs text-slate-600 mt-1">+{{ c.draft_count - 5 }} more drafts</div>
{% endif %}
</div>
{% endif %}
</div>
{% endfor %}
</div>