mockups/activity.html
Rama main · réplica de lectura del repositorio original.
<!DOCTYPE html>
<html lang="en" class="dark">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Activity feed — Cloudzilla</title>
<link rel="stylesheet" href="/assets/tailwind.css" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Geist+Mono:wght@400;500&family=Geist:wght@400;500;600&display=swap" rel="stylesheet" />
</head>
<body class="min-h-screen flex flex-col antialiased font-sans">
<a href="#main-content" class="skip-link">Skip to main content</a>
<div id="cz-header" data-account-tab="activity"></div>
<script src="shell.js"></script>
<main id="main-content" tabindex="-1" class="max-w-[1400px] mx-auto px-6 pt-6 pb-20 flex-1 w-full">
<section class="mb-6">
<h1 class="text-2xl font-semibold tracking-tight">Activity feed</h1>
<p class="mt-1 text-[13px] text-muted-foreground">Everything that's happened on your repos and the ones you watch.</p>
</section>
<nav class="mb-6 flex items-center gap-1 border-b border-border text-sm" aria-label="Activity scope" id="scopes">
<a href="#all" data-scope="all" class="px-3 py-2.5 border-b -mb-px inline-flex items-center gap-1.5">All activity <span class="ml-0.5 text-[11px] text-muted-foreground font-mono" aria-label="9 items">9</span></a>
<a href="#yours" data-scope="yours" class="px-3 py-2.5 border-b -mb-px inline-flex items-center gap-1.5">Your activity <span class="ml-0.5 text-[11px] text-muted-foreground font-mono" aria-label="4 items">4</span></a>
<a href="#watching" data-scope="watching" class="px-3 py-2.5 border-b -mb-px inline-flex items-center gap-1.5">Watching <span class="ml-0.5 text-[11px] text-muted-foreground font-mono" aria-label="5 items">5</span></a>
</nav>
<section class="border border-border rounded-md bg-card overflow-hidden" aria-labelledby="feed-heading" id="feed">
<h2 id="feed-heading" class="sr-only">Activity feed</h2>
<ol class="divide-y divide-border" id="rows"></ol>
</section>
<div id="empty" hidden class="bg-background border border-border rounded-lg p-8 text-center">
<p class="text-muted-foreground">No activity yet.</p>
<p class="text-sm text-muted-foreground mt-2">Watch some repositories to see events here.</p>
</div>
<div class="mt-6">
<div class="flex justify-between items-center pt-2">
<div></div>
<div><a href="activity.html" class="px-4 py-2 border border-border rounded-sm text-sm text-foreground hover:bg-muted/40">Next →</a></div>
</div>
</div>
</main>
<div id="cz-footer"></div>
<script>
(function () {
var I = {
pr_opened: '<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor" class="shrink-0 mt-1 text-success" aria-hidden="true"><path d="M1.5 3.25a2.25 2.25 0 113 2.122v5.256a2.251 2.251 0 11-1.5 0V5.372A2.25 2.25 0 011.5 3.25zm5.677-.177L9.573.677A.25.25 0 0110 .854V2.5h1A2.5 2.5 0 0113.5 5v5.628a2.251 2.251 0 11-1.5 0V5a1 1 0 00-1-1h-1v1.646a.25.25 0 01-.427.177L7.177 3.427a.25.25 0 010-.354zM3.75 2.5a.75.75 0 100 1.5.75.75 0 000-1.5zm0 9.5a.75.75 0 100 1.5.75.75 0 000-1.5zm8.25.75a.75.75 0 101.5 0 .75.75 0 00-1.5 0z"></path></svg>',
pr_merged: '<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor" class="shrink-0 mt-1 text-[hsl(270_70%_70%)]" aria-hidden="true"><path d="M5 3.254V3.25v.005a.75.75 0 110-.005v.004zm.45 1.9a2.25 2.25 0 10-1.95.218v5.256a2.25 2.25 0 101.5 0V7.123A5.735 5.735 0 009.25 9h1.378a2.251 2.251 0 100-1.5H9.25a4.25 4.25 0 01-3.8-2.346zM12.75 9a.75.75 0 100-1.5.75.75 0 000 1.5zm-8.5 4.5a.75.75 0 100-1.5.75.75 0 000 1.5z"></path></svg>',
issue_opened: '<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor" class="shrink-0 mt-1 text-success" aria-hidden="true"><path d="M8 9.5a1.5 1.5 0 100-3 1.5 1.5 0 000 3z"></path><path fill-rule="evenodd" d="M8 0a8 8 0 100 16A8 8 0 008 0zM1.5 8a6.5 6.5 0 1113 0 6.5 6.5 0 01-13 0z"></path></svg>',
issue_closed: '<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor" class="shrink-0 mt-1 text-destructive" aria-hidden="true"><path d="M11.28 6.78a.75.75 0 00-1.06-1.06L7.25 8.69 5.78 7.22a.75.75 0 00-1.06 1.06l2 2a.75.75 0 001.06 0l3.5-3.5z"></path><path fill-rule="evenodd" d="M16 8A8 8 0 110 8a8 8 0 0116 0zm-1.5 0a6.5 6.5 0 11-13 0 6.5 6.5 0 0113 0z"></path></svg>',
comment: '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" class="shrink-0 mt-1 text-muted-foreground" aria-hidden="true"><path d="M21 11.5a8.38 8.38 0 01-.9 3.8 8.5 8.5 0 01-7.6 4.7 8.38 8.38 0 01-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 01-.9-3.8 8.5 8.5 0 014.7-7.6 8.38 8.38 0 013.8-.9h.5a8.48 8.48 0 018 8v.5z"></path></svg>',
release: '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" class="shrink-0 mt-1 text-muted-foreground" aria-hidden="true"><path d="M20.59 13.41l-7.17 7.17a2 2 0 01-2.83 0L2 12V2h10l8.59 8.59a2 2 0 010 2.82z"></path><line x1="7" y1="7" x2="7.01" y2="7"></line></svg>',
push: '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" class="shrink-0 mt-1 text-muted-foreground" aria-hidden="true"><circle cx="12" cy="12" r="3"></circle><line x1="3" y1="12" x2="9" y2="12"></line><line x1="15" y1="12" x2="21" y2="12"></line></svg>'
};
var VERB = { pr_opened: 'opened', pr_merged: 'merged', issue_opened: 'opened', issue_closed: 'closed', comment: 'commented on', release: 'released' };
var EVENTS = [
{ k: 'pr_merged', a: 'daisy', repo: 'mkappworks/cloudzilla', ref: '#338', href: 'pr.html', when: '12 minutes ago', s: ['all', 'watching'] },
{ k: 'pr_opened', a: 'yumi', repo: 'mkappworks/cloudzilla', ref: '#341', href: 'pr.html', title: 'Add OAuth scopes to access tokens', when: '2 hours ago', s: ['all', 'watching'] },
{ k: 'push', a: 'mkappworks', repo: 'mkappworks/ingest-pipeline', branch: 'main', total: 5, commits: [['a3f9c21', 'Add replay window to consumer'], ['7be10d4', 'Backoff on ClickHouse insert errors'], ['c04e8aa', 'Bump kafka client']], when: '3 hours ago', s: ['all', 'yours'] },
{ k: 'issue_opened', a: 'daisy', repo: 'acme-corp/db', ref: '#88', href: 'issue_detail.html', title: 'Schema migration rollback plan', when: '8 hours ago', s: ['all', 'watching'] },
{ k: 'comment', a: 'mkappworks', repo: 'mkappworks/cloudzilla', ref: '#312', href: 'issue_detail.html', quote: 'Reproduced on main, bisecting now.', when: 'yesterday', s: ['all', 'yours'] },
{ k: 'issue_closed', a: 'kiyo', repo: 'openforge/runner', ref: '#41', href: 'issue_detail.html', when: '2 days ago', s: ['all', 'watching'] },
{ k: 'release', a: 'mkappworks', repo: 'mkappworks/cloudzilla', ref: 'v0.2.0', href: 'release_detail.html', title: 'Profile and organizations', when: '3 days ago', s: ['all', 'yours'] },
{ k: 'pr_merged', a: 'mkappworks', repo: 'mkappworks/cloudzilla', ref: '#330', href: 'pr.html', when: '4 days ago', s: ['all', 'yours'] },
{ k: 'pr_opened', a: 'kiyo', repo: 'openforge/runner', ref: '#57', href: 'pr.html', title: 'Sandbox resource limits', when: '5 days ago', s: ['all', 'watching'] }
];
function row(e) {
var head = '<a href="profile.html" class="font-medium hover:underline">' + e.a + '</a>';
if (e.k === 'push') head += '<span class="text-muted-foreground"> pushed </span><span class="font-mono">' + e.total + (e.total === 1 ? ' commit' : ' commits') + '</span><span class="text-muted-foreground"> to </span><span class="font-mono text-muted-foreground">' + e.branch + '</span>';
else head += '<span class="text-muted-foreground"> ' + VERB[e.k] + '</span>' + (e.ref ? '<span class="text-muted-foreground"> </span><a href="' + e.href + '" class="font-mono hover:underline text-primary">' + e.ref + '</a>' : '');
head += '<span class="text-muted-foreground">' + (e.k === 'star' || e.k === 'fork' ? ' ' : ' in ') + '</span><a href="repo.html" class="font-mono text-muted-foreground hover:underline">' + e.repo + '</a>';
var body = '';
if (e.k === 'push') body = '<ul class="mt-1 text-[12.5px] text-muted-foreground space-y-0.5">' + e.commits.map(function (c) { return '<li class="truncate"><span class="font-mono text-[11px] text-muted-foreground/70 mr-1">' + c[0] + '</span>' + c[1] + '</li>'; }).join('') + '<li class="text-[11px] text-muted-foreground/70">and ' + (e.total - e.commits.length) + ' more commits</li></ul>';
else if (e.quote) body = '<blockquote class="mt-1 pl-3 border-l border-border text-[12.5px] text-muted-foreground italic">“' + e.quote + '”</blockquote>';
else if (e.title) body = '<p class="mt-0.5 text-[12.5px] text-muted-foreground truncate">' + e.title + '</p>';
return '<li class="px-4 py-3 flex items-start gap-3 hover:bg-accent"><span class="flex shrink-0 mt-0.5 select-none"><span class="inline-grid place-items-center rounded-full bg-muted border border-border font-medium text-muted-foreground h-8 w-8 text-[11px]" aria-hidden="true">' + e.a[0].toUpperCase() + '</span></span>' +
'<div class="min-w-0 flex-1"><p class="text-[13px]">' + head + '</p>' + body + '<p class="mt-1 text-[11px] text-muted-foreground/70"><time>' + e.when + '</time></p></div>' + I[e.k] + '</li>';
}
var ON = 'px-3 py-2.5 border-b -mb-px border-foreground font-medium inline-flex items-center gap-1.5';
var OFF = 'px-3 py-2.5 border-b -mb-px border-transparent text-muted-foreground hover:text-foreground inline-flex items-center gap-1.5';
function render(scope) {
var rows = EVENTS.filter(function (e) { return e.s.indexOf(scope) >= 0; });
document.getElementById('rows').innerHTML = rows.map(row).join('');
document.getElementById('feed').hidden = !rows.length;
document.getElementById('empty').hidden = rows.length > 0;
document.querySelectorAll('#scopes a').forEach(function (a) {
var on = a.dataset.scope === scope;
a.className = on ? ON : OFF;
if (on) a.setAttribute('aria-current', 'page'); else a.removeAttribute('aria-current');
});
}
document.getElementById('scopes').addEventListener('click', function (e) {
var a = e.target.closest('a'); if (!a) return; e.preventDefault(); render(a.dataset.scope);
});
render('all');
})();
</script>
</body>
</html>