open source is social v-it.org
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix(explore): merge caps and skills in stats recent activity and pulse

The auto-resolved merge kept HEAD's caps-only renderStats and pulse
indicator. Restore the feature branch's improvements: recent activity
merges both caps and skills sorted by time, and the pulse indicator
checks both sources for the most recent network activity.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

+38 -14
+38 -14
explore/public/index.html
··· 647 647 } 648 648 649 649 async function renderStats(el) { 650 - const [data, recent] = await Promise.all([api('stats'), api('caps?limit=5')]); 651 - el.innerHTML = '<div class="stat-grid">' + 652 - '<div class="stat-card"><div class="stat-number">' + data.total_caps + '</div><div class="stat-label">capabilities</div></div>' + 653 - '<div class="stat-card"><div class="stat-number">' + data.total_vouches + '</div><div class="stat-label">vouches</div></div>' + 654 - '<div class="stat-card"><div class="stat-number">' + data.total_beacons + '</div><div class="stat-label">beacons</div></div>' + 655 - '<div class="stat-card"><div class="stat-number">' + data.active_dids + '</div><div class="stat-label">active participants</div></div>' + 656 - '<div class="stat-card"><div class="stat-number">' + data.total_skills + '</div><div class="stat-label">skills</div></div>' + 657 - '<div class="stat-card"><div class="stat-number">' + data.skill_publishers + '</div><div class="stat-label">skill publishers</div></div>' + 650 + const [stats, recentCaps, recentSkills] = await Promise.all([ 651 + api('stats'), 652 + api('caps?limit=5'), 653 + api('skills?limit=5') 654 + ]); 655 + const grid = '<div class="stat-grid">' + 656 + '<div class="stat-card"><div class="stat-number">' + stats.total_caps + '</div><div class="stat-label">capabilities</div></div>' + 657 + '<div class="stat-card"><div class="stat-number">' + stats.total_vouches + '</div><div class="stat-label">vouches</div></div>' + 658 + '<div class="stat-card"><div class="stat-number">' + stats.total_beacons + '</div><div class="stat-label">beacons</div></div>' + 659 + '<div class="stat-card"><div class="stat-number">' + stats.active_dids + '</div><div class="stat-label">active participants</div></div>' + 660 + '<div class="stat-card"><div class="stat-number">' + stats.total_skills + '</div><div class="stat-label">skills</div></div>' + 661 + '<div class="stat-card"><div class="stat-number">' + stats.skill_publishers + '</div><div class="stat-label">skill publishers</div></div>' + 658 662 '</div>'; 659 - if (recent.caps && recent.caps.length > 0) { 660 - el.innerHTML += '<div class="recent-activity"><h3>recent activity</h3>' + recent.caps.map(renderCapItem).join('') + '</div>'; 663 + 664 + const events = []; 665 + (recentCaps.caps || []).forEach(function(c) { events.push({ type: 'cap', label: c.title || c.ref || 'untitled', author: displayName(c), time: c.created_at }); }); 666 + (recentSkills.skills || []).forEach(function(s) { events.push({ type: 'skill', label: s.name || 'unnamed', author: displayName(s), time: s.created_at }); }); 667 + events.sort(function(a, b) { return (b.time || '').localeCompare(a.time || ''); }); 668 + events.splice(5); 669 + 670 + let activity = ''; 671 + if (events.length > 0) { 672 + activity = '<div class="recent-activity"><h3>recent activity</h3>' + 673 + events.map(function(e) { 674 + return '<div class="cap-item"><div class="cap-title">' + esc(e.label) + '</div><div class="cap-meta">' + esc(e.type) + ' · ' + esc(e.author) + ' · ' + timeAgo(e.time) + '</div></div>'; 675 + }).join('') + '</div>'; 661 676 } 677 + 678 + el.innerHTML = grid + activity; 662 679 } 663 680 664 - // Pulse indicator 665 - api('caps?limit=1').then(function(data) { 681 + // Pulse indicator — check both caps and skills for most recent activity 682 + Promise.all([api('caps?limit=1'), api('skills?limit=1')]).then(function(results) { 683 + var capData = results[0], skillData = results[1]; 684 + var latest = null; 685 + if (capData.caps && capData.caps.length > 0) latest = capData.caps[0].created_at; 686 + if (skillData.skills && skillData.skills.length > 0) { 687 + var skillTime = skillData.skills[0].created_at; 688 + if (!latest || skillTime > latest) latest = skillTime; 689 + } 666 690 var el = document.getElementById('pulse'); 667 - if (el && data.caps && data.caps.length > 0) { 668 - el.innerHTML = '<span class="pulse-dot"></span>last activity: ' + timeAgo(data.caps[0].created_at); 691 + if (el && latest) { 692 + el.innerHTML = '<span class="pulse-dot"></span>last activity: ' + timeAgo(latest); 669 693 } 670 694 }).catch(function() {}); 671 695