(entries)
| 8366 | o.textContent = i.name + tag; |
| 8367 | sel.appendChild(o); |
| 8368 | }); |
| 8369 | sel.dataset.filled = '1'; |
| 8370 | }).catch(() => {}); |
| 8371 | } |
| 8372 | async function runDtpWatch() { |
| 8373 | const out = document.getElementById('dtp-results'); |
| 8374 | if (!out) return; |
| 8375 | const btn = (typeof event !== 'undefined' && event && event.target) ? event.target : null; |
| 8376 | const ifaceSel = document.getElementById('dtp-iface'); |
| 8377 | const iface = ifaceSel && ifaceSel.value ? ifaceSel.value : ''; |
| 8378 | const secsEl = document.getElementById('dtp-secs'); |
| 8379 | const secs = secsEl && secsEl.value ? secsEl.value : '30'; |
| 8380 | _ndBusy(btn, true, 'Listening…'); |
| 8381 | out.classList.remove('hidden'); |
| 8382 | out.innerHTML = '<p class="text-sm text-gray-400">Passively capturing DTP frames (hellos are ~30s apart)…</p>'; |
| 8383 | try { |
| 8384 | _dtpFillIfaces(); |
| 8385 | const qs = '?seconds=' + encodeURIComponent(secs) + (iface ? '&interface=' + encodeURIComponent(iface) : ''); |
| 8386 | const d = await fetchAPI('/api/net/dtp-watch' + qs); |
| 8387 | if (!d || d.success === false) { |
| 8388 | const msg = (d && d.error) || 'failed'; |
| 8389 | let extra = ''; |
| 8390 | if (d && d.missing_tool) extra = ' <button onclick="installNetTool(\'tcpdump\', this, runDtpWatch)" class="ml-2 underline text-cyan-400">Install tcpdump</button>'; |
| 8391 | out.innerHTML = '<p class="text-sm text-red-400">Error: ' + escapeHtml(msg) + extra + '</p>'; |
| 8392 | return; |
| 8393 | } |
| 8394 | const [cls, label] = _DTP_VERDICT_STYLE[d.verdict] || _DTP_VERDICT_STYLE.unknown; |
| 8395 | let html = `<div class="mb-2 px-3 py-2 rounded border ${cls} text-sm">${label}</div>`; |
no test coverage detected