fix: show child count badge for filtered-out children; fetch missing child details in sidepane

Children outside the active status filter weren't in the local tickets array, causing
the row-level child count/toggle to be hidden and the sidepane to fall back to "#ID"
labels. Count badge now uses t.child_ids.length directly; sidepane fetches any missing
children via /api/tickets/{id} asynchronously.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
caoimhinr 2026-05-27 09:15:24 +02:00
parent 018f2f40a2
commit 87f5993149

View file

@ -701,14 +701,15 @@ async function loadTickets() {
function renderTicketRow(t) { function renderTicketRow(t) {
const visibleChildIds = (t.child_ids || []).filter(cid => tickets.some(c => c.id === cid)); const visibleChildIds = (t.child_ids || []).filter(cid => tickets.some(c => c.id === cid));
const childCount = visibleChildIds.length; const totalChildCount = (t.child_ids || []).length;
const visibleCount = visibleChildIds.length;
const expanded = expandedParents.has(t.id); const expanded = expandedParents.has(t.id);
return ` return `
<div class="ticket-row" onclick="showDetail(${t.id}); event.stopPropagation()"> <div class="ticket-row" onclick="showDetail(${t.id}); event.stopPropagation()">
<div class="tr-top"> <div class="tr-top">
<span class="tr-id">${t.human_id}</span> <span class="tr-id">${t.human_id}</span>
<span class="tr-title">${escHtml(t.title)}</span> <span class="tr-title">${escHtml(t.title)}</span>
${childCount ? `<button class="child-toggle" onclick="toggleChildren(${t.id}); event.stopPropagation()" title="${expanded ? 'Collapse' : 'Expand'} child tickets">${expanded ? '▾' : '▸'}</button><span class="child-count">${childCount}</span>` : ''} ${totalChildCount ? `${visibleCount ? `<button class="child-toggle" onclick="toggleChildren(${t.id}); event.stopPropagation()" title="${expanded ? 'Collapse' : 'Expand'} child tickets">${expanded ? '▾' : '▸'}</button>` : ''}<span class="child-count">${totalChildCount}</span>` : ''}
</div> </div>
<div class="tr-bottom"> <div class="tr-bottom">
${typeBadge(t.type)} ${typeBadge(t.type)}
@ -783,9 +784,19 @@ function showDetail(id) {
childList.innerHTML = t.child_ids.map(cid => { childList.innerHTML = t.child_ids.map(cid => {
const child = tickets.find(c => c.id === cid); const child = tickets.find(c => c.id === cid);
const label = child ? `${child.human_id} ${escHtml(child.title)}` : `#${cid}`; const label = child ? `${child.human_id} ${escHtml(child.title)}` : `#${cid}`;
return `<a class="child-link" onclick="showDetail(${cid}); event.stopPropagation()">${label}</a>`; return `<a class="child-link" id="child-ref-${cid}" onclick="showDetail(${cid}); event.stopPropagation()">${label}</a>`;
}).join(''); }).join('');
childWrap.style.display = ''; childWrap.style.display = '';
// Fetch any children that aren't in the current filtered ticket list
t.child_ids.forEach(async cid => {
if (!tickets.find(c => c.id === cid)) {
try {
const child = await api(`/api/tickets/${cid}`);
const el = document.getElementById(`child-ref-${cid}`);
if (el) el.textContent = `${child.human_id} ${child.title}`;
} catch(e) { /* keep fallback label */ }
}
});
} else { } else {
childWrap.style.display = 'none'; childWrap.style.display = 'none';
} }