diff --git a/corvid/templates/tickets_base.html b/corvid/templates/tickets_base.html index d65374b..7f1b5b6 100644 --- a/corvid/templates/tickets_base.html +++ b/corvid/templates/tickets_base.html @@ -527,6 +527,7 @@ let currentTicket = null; let expandedParents = new Set(); let currentAttach = null; let tickets = []; +let extraTickets = {}; let attachments = []; let environments = []; let currentEnvironmentId = null; @@ -699,17 +700,20 @@ async function loadTickets() { } } +function getTicketById(id) { + return tickets.find(t => t.id === id) || extraTickets[id] || null; +} + function renderTicketRow(t) { - const visibleChildIds = (t.child_ids || []).filter(cid => tickets.some(c => c.id === cid)); const totalChildCount = (t.child_ids || []).length; - const visibleCount = visibleChildIds.length; + const knownChildIds = (t.child_ids || []).filter(cid => getTicketById(cid)); const expanded = expandedParents.has(t.id); return `
${t.human_id} ${escHtml(t.title)} - ${totalChildCount ? `${visibleCount ? `` : ''}${totalChildCount}` : ''} + ${totalChildCount ? `${totalChildCount}` : ''}
${typeBadge(t.type)} @@ -722,7 +726,7 @@ function renderTicketRow(t) { ${t.attachment_count ? `·${t.attachment_count} file${t.attachment_count !== 1 ? 's' : ''}` : ''}
- ${visibleCount && expanded ? `
${visibleChildIds.map(cid => renderTicketRow(tickets.find(c => c.id === cid))).join('')}
` : ''} + ${knownChildIds.length && expanded ? `
${knownChildIds.map(cid => renderTicketRow(getTicketById(cid))).join('')}
` : ''} `; } @@ -753,9 +757,14 @@ function renderList() { list.innerHTML = roots.map(renderTicketRow).join(''); } -function showDetail(id) { - currentTicket = tickets.find(t => t.id === id); - if (!currentTicket) return; +async function showDetail(id) { + currentTicket = getTicketById(id); + if (!currentTicket) { + try { + currentTicket = await api(`/api/tickets/${id}`); + extraTickets[id] = currentTicket; + } catch(e) { return; } + } const t = currentTicket; document.getElementById('d-human-id').textContent = t.human_id; document.getElementById('d-title').textContent = t.title; @@ -782,16 +791,17 @@ function showDetail(id) { if (t.child_ids && t.child_ids.length) { const childList = document.getElementById('d-children-list'); childList.innerHTML = t.child_ids.map(cid => { - const child = tickets.find(c => c.id === cid); + const child = getTicketById(cid); const label = child ? `${child.human_id} ${escHtml(child.title)}` : `#${cid}`; return `${label}`; }).join(''); childWrap.style.display = ''; - // Fetch any children that aren't in the current filtered ticket list + // Fetch any children not in the local ticket list and cache them t.child_ids.forEach(async cid => { - if (!tickets.find(c => c.id === cid)) { + if (!getTicketById(cid)) { try { const child = await api(`/api/tickets/${cid}`); + extraTickets[child.id] = child; const el = document.getElementById(`child-ref-${cid}`); if (el) el.textContent = `${child.human_id} ${child.title}`; } catch(e) { /* keep fallback label */ }