()
| 10366 | } |
| 10367 | const [cls, label] = _FHRP_VERDICT_STYLE[d.verdict] || _FHRP_VERDICT_STYLE.unknown; |
| 10368 | let html = `<div class="mb-2 px-3 py-2 rounded border ${cls} text-sm">${label}</div>`; |
| 10369 | html += `<p class="text-xs text-gray-500 mb-2">Interface: ${escapeHtml(d.interface || '—')} · ${d.seconds}s · ${d.packet_count} hello(s), ${d.group_count} group(s) @ ${d.rate}/s${d.learned ? ' · <span class="text-gray-400">baseline learned now</span>' : ''}</p>`; |
| 10370 | (d.groups || []).forEach(g => { |
| 10371 | const auth = g.auth_weak ? `<span class="text-amber-300">${escapeHtml(g.authtype || 'none')} (weak)</span>` : escapeHtml(g.authtype || '—'); |
| 10372 | html += `<p class="text-xs uppercase text-gray-400 mt-2 mb-1">${escapeHtml(g.proto.toUpperCase())} group ${g.group == null ? '?' : g.group} · gateway ${escapeHtml((g.vips || []).join(', ') || '?')} · auth ${auth}</p>`; |
| 10373 | html += '<table class="min-w-full text-xs text-gray-300 whitespace-nowrap"><thead>' + |
| 10374 | '<tr class="text-left text-gray-500"><th class="px-2 py-1">Speaker</th><th class="px-2 py-1">Priority</th><th class="px-2 py-1">State/Op</th><th class="px-2 py-1">Status</th></tr>' + |
| 10375 | '</thead><tbody>' + |
| 10376 | (g.speakers || []).map(sp => { |
| 10377 | const badge = sp.baseline ? '<span class="text-green-400">✓ known</span>' : '<span class="text-amber-300">? new</span>'; |
| 10378 | const so = (sp.states || []).concat(sp.opcodes || []).join(', ') || '—'; |
| 10379 | return `<tr class="border-t border-slate-800"> |
| 10380 | <td class="px-2 py-1 font-mono ${sp.baseline ? '' : 'text-amber-300'}">${escapeHtml(sp.src)}</td> |
| 10381 | <td class="px-2 py-1 font-mono">${sp.priority == null ? '—' : sp.priority}</td> |
| 10382 | <td class="px-2 py-1 text-gray-400">${escapeHtml(so)}</td> |
| 10383 | <td class="px-2 py-1">${badge}</td> |
| 10384 | </tr>`; |
| 10385 | }).join('') + |
| 10386 | '</tbody></table>'; |
| 10387 | }); |
| 10388 | if ((d.glbp_forwarders || []).length) { |
| 10389 | html += '<p class="text-xs uppercase text-gray-400 mt-3 mb-1">GLBP forwarder plane (AVF)</p>'; |
| 10390 | html += '<table class="min-w-full text-xs text-gray-300 whitespace-nowrap"><thead>' + |
| 10391 | '<tr class="text-left text-gray-500"><th class="px-2 py-1">Group/Fwd</th><th class="px-2 py-1">Owner</th><th class="px-2 py-1">vMAC</th><th class="px-2 py-1">VF prio</th><th class="px-2 py-1">Weight</th><th class="px-2 py-1">State</th><th class="px-2 py-1">Status</th></tr>' + |
| 10392 | '</thead><tbody>'; |
| 10393 | (d.glbp_forwarders || []).forEach(fwd => { |
| 10394 | (fwd.owners || []).forEach(o => { |
| 10395 | const badge = o.baseline ? '<span class="text-green-400">✓ owner</span>' : '<span class="text-red-300">? new</span>'; |
| 10396 | html += `<tr class="border-t border-slate-800"> |
| 10397 | <td class="px-2 py-1 font-mono">${fwd.group}/${fwd.forwarder}</td> |
| 10398 | <td class="px-2 py-1 font-mono ${o.baseline ? '' : 'text-red-300'}">${escapeHtml(o.src)}</td> |
| 10399 | <td class="px-2 py-1 font-mono text-gray-400">${escapeHtml(o.vmac || '—')}</td> |
| 10400 | <td class="px-2 py-1 font-mono">${o.vf_priority == null ? '—' : o.vf_priority}</td> |
| 10401 | <td class="px-2 py-1 font-mono">${o.weight == null ? '—' : o.weight}</td> |
| 10402 | <td class="px-2 py-1 text-gray-400">${escapeHtml((o.states || []).join(', ') || '—')}</td> |
| 10403 | <td class="px-2 py-1">${badge}</td> |
| 10404 | </tr>`; |
| 10405 | }); |
| 10406 | }); |
| 10407 | html += '</tbody></table>'; |
| 10408 | } |
| 10409 | if (d.reasons && d.reasons.length) { |
| 10410 | html += '<ul class="text-xs text-gray-400 mt-2 list-disc pl-5">' + |
| 10411 | d.reasons.map(r => '<li>' + escapeHtml(r) + '</li>').join('') + '</ul>'; |
| 10412 | } |
| 10413 | (d.advisories || []).forEach(a => { |
| 10414 | html += `<div class="mt-2 px-3 py-2 rounded border text-xs text-gray-400 border-slate-700 bg-slate-900/40">${escapeHtml(a)}</div>`; |
| 10415 | }); |
| 10416 | out.innerHTML = html; |
| 10417 | } catch (e) { |
| 10418 | out.innerHTML = '<p class="text-sm text-red-400">Failed: ' + escapeHtml(e.message) + '</p>'; |
| 10419 | } finally { |
| 10420 | _ndBusy(btn, false); |
| 10421 | } |
nothing calls this directly
no test coverage detected