control: show instance identity (who/version/activation) + delete button
Renders applicant label/email, activation state and lease expiry per instance (was id-only), and a Delete button (DELETE /admin/licenses/:id) to clear dead test instances. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -200,14 +200,31 @@ async function renderInstances(panel) {
|
|||||||
const n = parseInt(d, 10);
|
const n = parseInt(d, 10);
|
||||||
if (Number.isFinite(n) && n !== 0) patch({ extend_days: n }, `extended +${n}d`);
|
if (Number.isFinite(n) && n !== 0) patch({ extend_days: n }, `extended +${n}d`);
|
||||||
}));
|
}));
|
||||||
|
// Hard delete — clears a dead/test instance + its record (vs Revoke, which keeps it).
|
||||||
|
actions.appendChild(btn('Delete', async () => {
|
||||||
|
const who = l.label || l.email || `#${l.id}`;
|
||||||
|
if (!confirm(`Permanently delete "${who}" and its record? This cannot be undone.`)) return;
|
||||||
|
try { await api.del(`${A}/licenses/${l.id}`); renderInstances(panel); }
|
||||||
|
catch (e) { notify(msg, e.message || 'delete failed', false); }
|
||||||
|
}, 'ghost'));
|
||||||
|
|
||||||
|
// Status cell: pill + activation state + lease expiry (more than just "active").
|
||||||
|
const statusCell = [
|
||||||
|
statusPill(l.status),
|
||||||
|
el('div', { class: 'muted', style: { fontSize: '0.68rem', marginTop: '0.15rem' } },
|
||||||
|
l.claimed ? 'activated' : 'awaiting activation'),
|
||||||
|
];
|
||||||
|
if (l.expires_at) statusCell.push(
|
||||||
|
el('div', { class: 'muted', style: { fontSize: '0.68rem' } }, `lease ends ${fmtTime(l.expires_at)}`));
|
||||||
|
|
||||||
return el('tr', {},
|
return el('tr', {},
|
||||||
td(el('strong', {}, l.label || l.email || `#${l.id}`), el('div', { class: 'muted', style: { fontSize: '0.72rem' } }, l.email || '')),
|
td(el('strong', {}, l.label || l.email || `#${l.id}`),
|
||||||
|
el('div', { class: 'muted', style: { fontSize: '0.72rem' } }, l.email && l.label ? l.email : `instance #${l.id}`)),
|
||||||
td(groupSel),
|
td(groupSel),
|
||||||
td(statusPill(l.status)),
|
td(...statusCell),
|
||||||
td(tierSel),
|
td(tierSel),
|
||||||
td(String(l.lease_days ?? '—')),
|
td(String(l.lease_days ?? '—')),
|
||||||
td(l.version || '—'),
|
td(l.version || el('span', { class: 'muted' }, 'unknown')),
|
||||||
td(el('span', { class: 'muted', style: { fontSize: '0.72rem' } }, fmtTime(l.last_seen || l.last_seen_at))),
|
td(el('span', { class: 'muted', style: { fontSize: '0.72rem' } }, fmtTime(l.last_seen || l.last_seen_at))),
|
||||||
td(actions, msg));
|
td(actions, msg));
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user