// Linux BenchTools - Device Detail Logic const { formatDate, formatRelativeTime, formatFileSize, createScoreBadge, getScoreBadgeText, escapeHtml, showError, showEmptyState, formatTags, initTabs, openModal, showToast, formatHardwareInfo } = window.BenchUtils; const api = window.BenchAPI; let currentDeviceId = null; let currentDevice = null; // Initialize page document.addEventListener('DOMContentLoaded', async () => { // Get device ID from URL currentDeviceId = window.BenchUtils.getUrlParameter('id'); if (!currentDeviceId) { document.getElementById('loadingState').innerHTML = '
Device ID manquant dans l\'URL
'; return; } // Initialize tabs initTabs('.tabs-container'); // Load device data await loadDeviceDetail(); }); // Load device detail async function loadDeviceDetail() { try { currentDevice = await api.getDevice(currentDeviceId); // Show content, hide loading document.getElementById('loadingState').style.display = 'none'; document.getElementById('deviceContent').style.display = 'block'; // Render all sections renderDeviceHeader(); renderHardwareSummary(); renderLastBenchmark(); renderNetworkDetails(); await loadBenchmarkHistory(); await loadDocuments(); await loadLinks(); } catch (error) { console.error('Failed to load device:', error); document.getElementById('loadingState').innerHTML = `
Erreur lors du chargement du device: ${escapeHtml(error.message)}
`; } } // Render device header function renderDeviceHeader() { document.getElementById('deviceHostname').textContent = currentDevice.hostname; document.getElementById('deviceDescription').textContent = currentDevice.description || 'Aucune description'; // Global score const globalScore = currentDevice.last_benchmark?.global_score; document.getElementById('globalScoreContainer').innerHTML = globalScore !== null && globalScore !== undefined ? `
${getScoreBadgeText(globalScore)}
` : 'N/A'; // Meta information const metaParts = []; if (currentDevice.location) metaParts.push(`📍 ${escapeHtml(currentDevice.location)}`); if (currentDevice.owner) metaParts.push(`👤 ${escapeHtml(currentDevice.owner)}`); if (currentDevice.asset_tag) metaParts.push(`🏷️ ${escapeHtml(currentDevice.asset_tag)}`); if (currentDevice.last_benchmark?.run_at) metaParts.push(`⏱️ ${formatRelativeTime(currentDevice.last_benchmark.run_at)}`); document.getElementById('deviceMeta').innerHTML = metaParts.map(part => `${part}` ).join(''); // Tags if (currentDevice.tags) { document.getElementById('deviceTags').innerHTML = formatTags(currentDevice.tags); } } // Render hardware summary function renderHardwareSummary() { const snapshot = currentDevice.last_hardware_snapshot; if (!snapshot) { document.getElementById('hardwareSummary').innerHTML = '

Aucune information hardware disponible

'; return; } // RAM usage info const ramTotalGB = Math.round((snapshot.ram_total_mb || 0) / 1024); const ramUsedMB = snapshot.ram_used_mb || 0; const ramFreeMB = snapshot.ram_free_mb || 0; const ramSharedMB = snapshot.ram_shared_mb || 0; let ramValue = `${ramTotalGB} GB`; if (ramUsedMB > 0 || ramFreeMB > 0) { const usagePercent = ramTotalGB > 0 ? Math.round((ramUsedMB / (snapshot.ram_total_mb || 1)) * 100) : 0; ramValue = `${ramTotalGB} GB (${usagePercent}% utilisé)
Utilisée: ${Math.round(ramUsedMB / 1024)}GB • Libre: ${Math.round(ramFreeMB / 1024)}GB`; if (ramSharedMB > 0) { ramValue += ` • Partagée: ${Math.round(ramSharedMB / 1024)}GB`; } ramValue += `
${snapshot.ram_slots_used || '?'} / ${snapshot.ram_slots_total || '?'} slots
`; } else { ramValue += `
${snapshot.ram_slots_used || '?'} / ${snapshot.ram_slots_total || '?'} slots`; } const hardwareItems = [ { label: 'CPU', icon: '🔲', value: `${snapshot.cpu_model || 'N/A'}
${snapshot.cpu_cores || 0}C / ${snapshot.cpu_threads || 0}T @ ${snapshot.cpu_max_freq_ghz || snapshot.cpu_base_freq_ghz || '?'} GHz` }, { label: 'RAM', icon: '💾', value: ramValue }, { label: 'GPU', icon: '🎮', value: snapshot.gpu_model || snapshot.gpu_summary || 'N/A' }, { label: 'Stockage', icon: '💿', value: snapshot.storage_summary || 'N/A' }, { label: 'Réseau', icon: '🌐', value: snapshot.network_interfaces_json ? `${JSON.parse(snapshot.network_interfaces_json).length} interface(s)` : 'N/A' }, { label: 'Carte mère', icon: '⚡', value: `${snapshot.motherboard_vendor || ''} ${snapshot.motherboard_model || 'N/A'}` }, { label: 'OS', icon: '🐧', value: `${snapshot.os_name || 'N/A'} ${snapshot.os_version || ''}
Kernel ${snapshot.kernel_version || 'N/A'}` }, { label: 'Architecture', icon: '🏗️', value: snapshot.architecture || 'N/A' }, { label: 'Virtualisation', icon: '📦', value: snapshot.virtualization_type || 'none' } ]; document.getElementById('hardwareSummary').innerHTML = hardwareItems.map(item => `
${item.icon} ${item.label}
${item.value}
`).join(''); } // Render last benchmark scores function renderLastBenchmark() { const bench = currentDevice.last_benchmark; if (!bench) { document.getElementById('lastBenchmark').innerHTML = '

Aucun benchmark disponible

'; return; } document.getElementById('lastBenchmark').innerHTML = `
Date: ${formatDate(bench.run_at)} Version: ${escapeHtml(bench.bench_script_version || 'N/A')}
${createScoreBadge(bench.global_score, 'Global')} ${createScoreBadge(bench.cpu_score, 'CPU')} ${createScoreBadge(bench.memory_score, 'Mémoire')} ${createScoreBadge(bench.disk_score, 'Disque')} ${createScoreBadge(bench.network_score, 'Réseau')} ${createScoreBadge(bench.gpu_score, 'GPU')}
`; } // Render network details function renderNetworkDetails() { const container = document.getElementById('networkDetails'); const snapshot = currentDevice.last_hardware_snapshot; const bench = currentDevice.last_benchmark; if (!snapshot || !snapshot.network_interfaces_json) { container.innerHTML = '

Aucune information réseau disponible

'; return; } try { const interfaces = JSON.parse(snapshot.network_interfaces_json); if (!interfaces || interfaces.length === 0) { container.innerHTML = '

Aucune interface réseau détectée

'; return; } let html = '
'; // Interface details interfaces.forEach(iface => { const typeIcon = iface.type === 'ethernet' ? '🔌' : (iface.type === 'wifi' ? '📡' : '🌐'); const wol = iface.wake_on_lan; const wolBadge = wol === true ? 'WoL ✓' : (wol === false ? 'WoL ✗' : ''); html += `
${typeIcon} ${escapeHtml(iface.name)}
${escapeHtml(iface.type || 'unknown')}
${wolBadge}
${iface.ip ? `
IP: ${escapeHtml(iface.ip)}
` : ''} ${iface.mac ? `
MAC: ${escapeHtml(iface.mac)}
` : ''} ${iface.speed_mbps ? `
Vitesse: ${iface.speed_mbps} Mbps
` : ''} ${iface.driver ? `
Driver: ${escapeHtml(iface.driver)}
` : ''}
`; }); // Network benchmark results (iperf3) if (bench && bench.network_score !== null && bench.network_score !== undefined) { let netBenchHtml = '
'; netBenchHtml += '
📈 Résultats Benchmark Réseau (iperf3)
'; netBenchHtml += '
'; // Try to parse network_results_json if available let uploadMbps = null; let downloadMbps = null; let pingMs = null; if (bench.network_results_json) { try { const netResults = typeof bench.network_results_json === 'string' ? JSON.parse(bench.network_results_json) : bench.network_results_json; uploadMbps = netResults.upload_mbps; downloadMbps = netResults.download_mbps; pingMs = netResults.ping_ms; } catch (e) { console.warn('Failed to parse network_results_json:', e); } } if (uploadMbps !== null && uploadMbps !== undefined) { netBenchHtml += `
↑ ${uploadMbps.toFixed(2)}
Upload Mbps
`; } if (downloadMbps !== null && downloadMbps !== undefined) { netBenchHtml += `
↓ ${downloadMbps.toFixed(2)}
Download Mbps
`; } if (pingMs !== null && pingMs !== undefined) { netBenchHtml += `
${typeof pingMs === 'number' ? pingMs.toFixed(2) : pingMs}
Ping ms
`; } netBenchHtml += `
${bench.network_score.toFixed(2)}
Score
`; netBenchHtml += '
'; html += netBenchHtml; } html += '
'; container.innerHTML = html; } catch (error) { console.error('Failed to parse network interfaces:', error); container.innerHTML = '

Erreur lors du parsing des données réseau

'; } } // Load benchmark history async function loadBenchmarkHistory() { const container = document.getElementById('benchmarkHistory'); try { const data = await api.getDeviceBenchmarks(currentDeviceId, { limit: 20 }); if (!data.items || data.items.length === 0) { showEmptyState(container, 'Aucun benchmark dans l\'historique', '📊'); return; } container.innerHTML = `
${data.items.map(bench => ` `).join('')}
Date Score Global CPU MEM DISK NET GPU Version Action
${formatDate(bench.run_at)} ${getScoreBadgeText(bench.global_score)} ${getScoreBadgeText(bench.cpu_score)} ${getScoreBadgeText(bench.memory_score)} ${getScoreBadgeText(bench.disk_score)} ${getScoreBadgeText(bench.network_score)} ${getScoreBadgeText(bench.gpu_score)} ${escapeHtml(bench.bench_script_version || 'N/A')}
`; } catch (error) { console.error('Failed to load benchmarks:', error); showError(container, 'Erreur lors du chargement de l\'historique'); } } // View benchmark details async function viewBenchmarkDetails(benchmarkId) { const modalBody = document.getElementById('benchmarkModalBody'); openModal('benchmarkModal'); try { const benchmark = await api.getBenchmark(benchmarkId); modalBody.innerHTML = `
${JSON.stringify(benchmark.details || benchmark, null, 2)}
`; } catch (error) { console.error('Failed to load benchmark details:', error); modalBody.innerHTML = `
Erreur: ${escapeHtml(error.message)}
`; } } // Load documents async function loadDocuments() { const container = document.getElementById('documentsList'); try { const docs = await api.getDeviceDocs(currentDeviceId); if (!docs || docs.length === 0) { showEmptyState(container, 'Aucun document uploadé', '📄'); return; } container.innerHTML = ` `; } catch (error) { console.error('Failed to load documents:', error); showError(container, 'Erreur lors du chargement des documents'); } } // Get document icon function getDocIcon(docType) { const icons = { manual: '📘', warranty: '📜', invoice: '🧾', photo: '📷', other: '📄' }; return icons[docType] || '📄'; } // Upload document async function uploadDocument() { const fileInput = document.getElementById('fileInput'); const docTypeSelect = document.getElementById('docTypeSelect'); if (!fileInput.files || fileInput.files.length === 0) { showToast('Veuillez sélectionner un fichier', 'error'); return; } const file = fileInput.files[0]; const docType = docTypeSelect.value; try { await api.uploadDocument(currentDeviceId, file, docType); showToast('Document uploadé avec succès', 'success'); // Reset form fileInput.value = ''; docTypeSelect.value = 'manual'; // Reload documents await loadDocuments(); } catch (error) { console.error('Failed to upload document:', error); showToast('Erreur lors de l\'upload: ' + error.message, 'error'); } } // Delete document async function deleteDocument(docId) { if (!confirm('Êtes-vous sûr de vouloir supprimer ce document ?')) { return; } try { await api.deleteDocument(docId); showToast('Document supprimé', 'success'); await loadDocuments(); } catch (error) { console.error('Failed to delete document:', error); showToast('Erreur lors de la suppression: ' + error.message, 'error'); } } // Load links async function loadLinks() { const container = document.getElementById('linksList'); try { const links = await api.getDeviceLinks(currentDeviceId); if (!links || links.length === 0) { showEmptyState(container, 'Aucun lien ajouté', '🔗'); return; } container.innerHTML = ` `; } catch (error) { console.error('Failed to load links:', error); showError(container, 'Erreur lors du chargement des liens'); } } // Add link async function addLink() { const labelInput = document.getElementById('linkLabel'); const urlInput = document.getElementById('linkUrl'); const label = labelInput.value.trim(); const url = urlInput.value.trim(); if (!label || !url) { showToast('Veuillez remplir tous les champs', 'error'); return; } try { await api.addDeviceLink(currentDeviceId, { label, url }); showToast('Lien ajouté avec succès', 'success'); // Reset form labelInput.value = ''; urlInput.value = ''; // Reload links await loadLinks(); } catch (error) { console.error('Failed to add link:', error); showToast('Erreur lors de l\'ajout: ' + error.message, 'error'); } } // Delete link async function deleteLink(linkId) { if (!confirm('Êtes-vous sûr de vouloir supprimer ce lien ?')) { return; } try { await api.deleteLink(linkId); showToast('Lien supprimé', 'success'); await loadLinks(); } catch (error) { console.error('Failed to delete link:', error); showToast('Erreur lors de la suppression: ' + error.message, 'error'); } } // Make functions available globally window.viewBenchmarkDetails = viewBenchmarkDetails; window.uploadDocument = uploadDocument; window.deleteDocument = deleteDocument; window.addLink = addLink; window.deleteLink = deleteLink;