MCPcopy Create free account
hub / github.com/PierreGode/Ragnar / renderDashboardInterfaceSwitch

Function renderDashboardInterfaceSwitch

web/scripts/ragnar_modern.js:8880–8919  ·  view source on GitHub ↗
(state)

Source from the content-addressed store, hash-verified

8878 _ndBusy(btn, true, 'Listening…');
8879 out.classList.remove('hidden');
8880 out.innerHTML = '<p class="text-sm text-gray-400">Passively capturing FHRP hellos on the segment…</p>';
8881 try {
8882 _fhrpFillIfaces();
8883 const qs = '?seconds=' + encodeURIComponent(secs) + (iface ? '&interface=' + encodeURIComponent(iface) : '');
8884 const d = await fetchAPI('/api/net/fhrp-watch' + qs);
8885 if (!d || d.success === false) {
8886 const msg = (d && d.error) || 'failed';
8887 let extra = '';
8888 if (d && d.missing_tool) extra = ' <button onclick="installNetTool(\'tcpdump\', this, runFhrpWatch)" class="ml-2 underline text-cyan-400">Install tcpdump</button>';
8889 out.innerHTML = '<p class="text-sm text-red-400">Error: ' + escapeHtml(msg) + extra + '</p>';
8890 return;
8891 }
8892 const [cls, label] = _FHRP_VERDICT_STYLE[d.verdict] || _FHRP_VERDICT_STYLE.unknown;
8893 let html = `<div class="mb-2 px-3 py-2 rounded border ${cls} text-sm">${label}</div>`;
8894 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>`;
8895 (d.groups || []).forEach(g => {
8896 const auth = g.auth_weak ? `<span class="text-amber-300">${escapeHtml(g.authtype || 'none')} (weak)</span>` : escapeHtml(g.authtype || '—');
8897 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>`;
8898 html += '<table class="min-w-full text-xs text-gray-300 whitespace-nowrap"><thead>' +
8899 '<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>' +
8900 '</thead><tbody>' +
8901 (g.speakers || []).map(sp => {
8902 const badge = sp.baseline ? '<span class="text-green-400">✓ known</span>' : '<span class="text-amber-300">? new</span>';
8903 const so = (sp.states || []).concat(sp.opcodes || []).join(', ') || '—';
8904 return `<tr class="border-t border-slate-800">
8905 <td class="px-2 py-1 font-mono ${sp.baseline ? '' : 'text-amber-300'}">${escapeHtml(sp.src)}</td>
8906 <td class="px-2 py-1 font-mono">${sp.priority == null ? '—' : sp.priority}</td>
8907 <td class="px-2 py-1 text-gray-400">${escapeHtml(so)}</td>
8908 <td class="px-2 py-1">${badge}</td>
8909 </tr>`;
8910 }).join('') +
8911 '</tbody></table>';
8912 });
8913 if ((d.glbp_forwarders || []).length) {
8914 html += '<p class="text-xs uppercase text-gray-400 mt-3 mb-1">GLBP forwarder plane (AVF)</p>';
8915 html += '<table class="min-w-full text-xs text-gray-300 whitespace-nowrap"><thead>' +
8916 '<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>' +
8917 '</thead><tbody>';
8918 (d.glbp_forwarders || []).forEach(fwd => {
8919 (fwd.owners || []).forEach(o => {
8920 const badge = o.baseline ? '<span class="text-green-400">✓ owner</span>' : '<span class="text-red-300">? new</span>';
8921 html += `<tr class="border-t border-slate-800">
8922 <td class="px-2 py-1 font-mono">${fwd.group}/${fwd.forwarder}</td>

Callers 1

Calls 6

filterMethod · 0.80
addMethod · 0.80
getActiveWifiInterfaceFunction · 0.70
escapeHtmlFunction · 0.70
setSelectedWifiInterfaceFunction · 0.70

Tested by

no test coverage detected