generated from coulomb/repo-seed
Implement dashboard UI improvements
This commit is contained in:
@@ -19,6 +19,10 @@ const gdprReport = await fetch(`${API}/tpsc/report/gdpr`)
|
||||
const snapshots = await fetch(`${API}/tpsc/snapshots/`)
|
||||
.then(r => r.json())
|
||||
.catch(() => []);
|
||||
|
||||
const repos = await fetch(`${API}/repos/`)
|
||||
.then(r => r.ok ? r.json() : [])
|
||||
.catch(() => []);
|
||||
```
|
||||
|
||||
```js
|
||||
@@ -150,12 +154,41 @@ if (gdprReport.warnings.length === 0) {
|
||||
## Per-Repo Breakdown
|
||||
|
||||
```js
|
||||
const repoById = Object.fromEntries(repos.map(r => [r.id, r]));
|
||||
const repoBySlug = Object.fromEntries(repos.map(r => [r.slug, r]));
|
||||
|
||||
function repoForSnapshotKey(repoKey) {
|
||||
return repoById[repoKey] ?? repoBySlug[repoKey] ?? null;
|
||||
}
|
||||
|
||||
function repoWebUrl(repo) {
|
||||
const url = repo?.remote_url ?? "";
|
||||
return /^https?:\/\//.test(url) ? url : null;
|
||||
}
|
||||
|
||||
function repoCell(repoKey) {
|
||||
const repo = repoForSnapshotKey(repoKey);
|
||||
const webUrl = repoWebUrl(repo);
|
||||
const label = repo?.name || repo?.slug || repoKey || "unknown repo";
|
||||
const slug = repo?.slug ?? repoKey ?? "unknown";
|
||||
const domain = repo?.domain_slug ?? "unknown";
|
||||
const content = html`<div class="repo-ref">
|
||||
<div class="repo-ref-name">
|
||||
${webUrl
|
||||
? html`<a href="${webUrl}" target="_blank" rel="noopener noreferrer">${label}</a>`
|
||||
: label}
|
||||
</div>
|
||||
<div class="repo-ref-meta">${domain} / ${slug}</div>
|
||||
</div>`;
|
||||
return content;
|
||||
}
|
||||
|
||||
// Build: latest snapshot per repo → service list
|
||||
const repoBreakdown = new Map();
|
||||
for (const snap of snapshots) {
|
||||
const repoSlug = snap.repo_id || "unknown";
|
||||
if (!repoBreakdown.has(repoSlug) || snap.snapshot_at > repoBreakdown.get(repoSlug).snapshot_at) {
|
||||
repoBreakdown.set(repoSlug, snap);
|
||||
const repoKey = snap.repo_id || snap.repo_slug || "unknown";
|
||||
if (!repoBreakdown.has(repoKey) || snap.snapshot_at > repoBreakdown.get(repoKey).snapshot_at) {
|
||||
repoBreakdown.set(repoKey, snap);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,8 +204,8 @@ const repoTable = html`<table style="width:100%; border-collapse:collapse; font-
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
${[...repoBreakdown.entries()].map(([repoSlug, snap]) => html`<tr style="border-bottom:1px solid #f3f4f6;">
|
||||
<td style="padding:8px 12px; font-weight:500;">${repoSlug}</td>
|
||||
${[...repoBreakdown.entries()].map(([repoKey, snap]) => html`<tr style="border-bottom:1px solid #f3f4f6;">
|
||||
<td style="padding:8px 12px; font-weight:500;">${repoCell(repoKey)}</td>
|
||||
<td style="padding:8px 12px;">
|
||||
${snap.entries.map(e => {
|
||||
const cat = catalogBySlug[e.service_slug];
|
||||
@@ -191,3 +224,27 @@ const repoTable = html`<table style="width:100%; border-collapse:collapse; font-
|
||||
</table>`;
|
||||
display(repoTable);
|
||||
```
|
||||
|
||||
<style>
|
||||
.repo-ref {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.1rem;
|
||||
}
|
||||
.repo-ref-name {
|
||||
font-weight: 600;
|
||||
color: var(--theme-foreground, #111);
|
||||
}
|
||||
.repo-ref-name a {
|
||||
color: #1d4ed8;
|
||||
text-decoration: none;
|
||||
}
|
||||
.repo-ref-name a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.repo-ref-meta {
|
||||
font-size: 0.76rem;
|
||||
font-weight: 400;
|
||||
color: var(--theme-foreground-muted, #6b7280);
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user