// services/renderers/mppPhoneFormatters.js // // Display helpers for MPP phone diagnostics follow-up messages. import { formatMicCertForDisplay } from '../../integrations/cisco-mpp-phone/downloadStatusJson.js'; export function shortenFirmware(fw) { if (!fw || typeof fw !== 'string') return '?'; const m = fw.match(/(sip78xx[^\s]+)/i); return m ? m[1] : (fw.length > 36 ? `${fw.slice(0, 36)}…` : fw); } /** @param {string|null|undefined} elapsedTime */ export function formatUptime(elapsedTime) { if (!elapsedTime || typeof elapsedTime !== 'string') return null; const trimmed = elapsedTime.trim(); if (!trimmed) return null; const dayHour = trimmed.match(/(\d+)\s+days?\s+and\s+(\d+):(\d+):(\d+)/i); if (dayHour) { const days = Number(dayHour[1]); const hours = Number(dayHour[2]); if (days > 0) return `${days}d ${hours}h`; if (hours > 0) return `${hours}h`; return `${Number(dayHour[3])}m`; } const hms = trimmed.match(/^(\d+):(\d+):(\d+)$/); if (hms) { const hours = Number(hms[1]); const mins = Number(hms[2]); if (hours > 0) return `${hours}h ${mins}m`; return `${mins}m`; } return trimmed.length > 24 ? `${trimmed.slice(0, 24)}…` : trimmed; } /** @param {object} phoneStatus @param {object} neighbor */ export function formatLinkSpeed(phoneStatus = {}, neighbor = {}) { const fromStatus = phoneStatus.linkSpeed || phoneStatus.linkConfig || null; if (fromStatus && fromStatus !== 'Disabled') return String(fromStatus).trim(); const fromLldp = neighbor.portSpeed ? String(neighbor.portSpeed).trim() : null; if (fromLldp) { const compact = fromLldp.replace(/\s+/g, ' '); if (/^\d+F$/i.test(compact)) return compact.replace(/F$/i, 'M Full'); return compact; } return null; } export function formatHeaderStatusLine(phoneStatus, neighbor) { const uptime = formatUptime(phoneStatus?.elapsedTime); const link = formatLinkSpeed(phoneStatus, neighbor); const parts = []; if (uptime) parts.push(`Uptime ${uptime}`); if (link) parts.push(link); return parts.length ? parts.join(' · ') : null; } export function isLineRegistered(line) { const state = String(line?.registrationState || '').toLowerCase(); if (!state) return false; if (state.includes('not registered') || state.includes('fail')) return false; return state.includes('registered'); } export function headerIconForLine(line) { if (!line?.registrationState) return '⚠️'; return isLineRegistered(line) ? '✅' : '❌'; } export function formatRebootEntry(raw) { if (!raw) return null; const m = String(raw).match(/^(\w+)\(([^)]+)\)/); if (m) return `${m[1]} @ ${m[2]}`; return String(raw); } export function hostFromUrl(url) { if (!url || typeof url !== 'string') return '?'; try { const normalized = url.startsWith('http') ? url : `https://${url}`; return new URL(normalized).hostname; } catch { return url.length > 30 ? `${url.slice(0, 30)}…` : url; } } export function formatProvisioningResync(entry) { if (!entry) return null; const host = entry.url ? hostFromUrl(entry.url) : '?'; const result = entry.succeeded ? 'OK' : (entry.failed ? 'FAILED' : (entry.result || '?')); return `Resync: ${host} · ${result}`; } export function formatFirmwareUpgrade(entry) { if (!entry) return null; if (entry.succeeded) return 'Firmware upgrade: OK'; if (entry.failed) return `Firmware upgrade: ${entry.result || 'FAILED'}`; return null; } /** * @param {object} mpp buildMppProbeView output * @param {object} parsed * @returns {string[]} */ export function collectIssues(mpp, parsed) { const issues = []; const download = mpp?.download; const mic = formatMicCertForDisplay(download?.micCert); if (mic) issues.push(mic); if (download?.latestProvisioning?.failed) { const host = download.latestProvisioning.url ? hostFromUrl(download.latestProvisioning.url) : '?'; issues.push(`Provisioning resync failed — ${host}`); } if (download?.latestFirmwareUpgrade?.failed) { issues.push(`Firmware upgrade failed — ${download.latestFirmwareUpgrade.result || 'unknown'}`); } const line1 = parsed?.lines?.find((l) => l.index === 1) || parsed?.lines?.[0]; if (line1?.registrationState && !isLineRegistered(line1)) { issues.push(`Ext ${line1.index}: ${line1.registrationState}`); } return issues; }