feat(v0.1.5): SMART multi-disques — collecte tous les disques détectés
Agent: - SmartMetrics + champ device (nom du disque ex: sda, nvme0) - smart: Option<Vec<SmartMetrics>> — tous les disques, pas seulement le 1er - collect() itère /sys/block, accumule les résultats de tous les disques valides Serveur: - SmartMetrics.Device + Smart []SmartMetrics dans AgentMetrics - InsertMetrics: stocke smart_json (JSON array) au lieu de colonnes plates - GetLastMetrics: désérialise smart_json - Migration: smart_json TEXT ajoutée Dashboard: - Tuile: une icône shield/triangle par disque avec tooltip incluant le nom - Popup détail: un bouton SMART par disque (couleur ok/err) - showSmart(agentId, diskIdx): affiche le disque sélectionné Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -77,10 +77,11 @@ const Grid = (() => {
|
||||
uptimeStr = d > 0 ? `${d}j ${h}h` : `${h}h`;
|
||||
}
|
||||
|
||||
const smartIco = !offline && metrics?.smart != null
|
||||
? (metrics.smart.passed
|
||||
? `<i class="fa-solid fa-shield-check" style="color:var(--ok);font-size:10px;flex-shrink:0" data-tip="SMART OK"></i>`
|
||||
: `<i class="fa-solid fa-triangle-exclamation" style="color:var(--err);font-size:10px;flex-shrink:0" data-tip="SMART FAILED"></i>`)
|
||||
const smartIco = !offline && metrics?.smart?.length > 0
|
||||
? metrics.smart.map(s => s.passed
|
||||
? `<i class="fa-solid fa-shield-check" style="color:var(--ok);font-size:10px;flex-shrink:0" data-tip="SMART OK — ${s.device}"></i>`
|
||||
: `<i class="fa-solid fa-triangle-exclamation" style="color:var(--err);font-size:10px;flex-shrink:0" data-tip="SMART FAILED — ${s.device}"></i>`
|
||||
).join('')
|
||||
: '';
|
||||
|
||||
const iconContent = `<img src="${API.iconUrl(id)}" alt=""
|
||||
|
||||
+13
-11
@@ -80,15 +80,16 @@ const Popups = (() => {
|
||||
? `<div class="chart-minmax"><span>min ${Grid.fmt(ramMin)}</span><span>max ${Grid.fmt(ramMax)}</span></div>`
|
||||
: '';
|
||||
|
||||
const smartBtn = metrics?.smart
|
||||
? `<div class="smart-btn ok" onclick="Popups.showSmart('${esc(agentId)}')" data-tip="Voir la santé complète du disque">
|
||||
<div class="smart-dot"></div>
|
||||
<span style="font-weight:600">SMART</span>
|
||||
const smartBtn = metrics?.smart?.length > 0
|
||||
? metrics.smart.map((s, i) => `
|
||||
<div class="smart-btn ${s.passed ? 'ok' : 'err'}" onclick="Popups.showSmart('${esc(agentId)}',${i})" data-tip="Voir la santé du disque ${esc(s.device)}">
|
||||
<div class="smart-dot" style="${s.passed ? '' : 'background:var(--err);box-shadow:0 0 5px var(--err)'}"></div>
|
||||
<span style="font-weight:600">${esc(s.device) || 'disque'}</span>
|
||||
<span>·</span>
|
||||
<span>${metrics.smart.passed ? 'PASSED' : 'FAILED'}</span>
|
||||
${metrics.smart.temperature ? `<span style="font-family:var(--font-mono);font-size:10px;color:var(--ink-3)"><i class="fa-solid fa-temperature-half"></i> ${metrics.smart.temperature}°C</span>` : ''}
|
||||
<span>${s.passed ? 'PASSED' : 'FAILED'}</span>
|
||||
${s.temperature != null ? `<span style="font-family:var(--font-mono);font-size:10px;color:var(--ink-3)"><i class="fa-solid fa-temperature-half"></i> ${s.temperature}°C</span>` : ''}
|
||||
<i class="fa-solid fa-chevron-right" style="font-size:10px;color:var(--ink-4);margin-left:auto"></i>
|
||||
</div>`
|
||||
</div>`).join('')
|
||||
: '';
|
||||
|
||||
const protos = [
|
||||
@@ -389,10 +390,11 @@ const Popups = (() => {
|
||||
}
|
||||
|
||||
// ══ POPUP SMART ══
|
||||
function showSmart(agentId) {
|
||||
const m = Grid.getAgent(agentId)?.metrics?.smart;
|
||||
if (!m) return;
|
||||
document.getElementById('smart-sub').textContent = agentId;
|
||||
function showSmart(agentId, diskIdx = 0) {
|
||||
const smartList = Grid.getAgent(agentId)?.metrics?.smart;
|
||||
if (!smartList?.length) return;
|
||||
const m = smartList[diskIdx] ?? smartList[0];
|
||||
document.getElementById('smart-sub').textContent = m.device ? `${agentId} — ${m.device}` : agentId;
|
||||
const passColor = m.passed ? 'var(--ok)' : 'var(--err)';
|
||||
const passText = m.passed ? 'Disque en bonne santé' : 'Disque en mauvais état';
|
||||
const passSub = m.passed
|
||||
|
||||
Reference in New Issue
Block a user