feat: type de jauge configurable (compact / standard)
- ServerConfig: champ gauge_type (défaut "compact") - CSS: classes .gs-* pour la BatteryGauge standard (label + bar 9px + gloss interne) - Grid: helper renderGaugeRow() — sélectionne compact ou standard selon la config - Grid: rerenderAll() pour appliquer le changement sans recharger la page - Popup config serveur: select "Type de jauge" dans la section Affichage des tuiles Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -117,6 +117,17 @@ body{background:var(--bg-1);color:var(--ink-1);font-family:var(--font-ui);font-s
|
||||
.g-fill.w{background:var(--warn)}.g-fill.e{background:var(--err)}
|
||||
.g-val{font-family:var(--font-mono);font-size:11px;color:var(--ink-2);
|
||||
min-width:34px;white-space:nowrap;flex-shrink:0;text-align:right}
|
||||
/* Jauge standard (BatteryGauge) */
|
||||
.gs-row{display:flex;flex-direction:column;gap:3px}
|
||||
.gs-header{display:flex;align-items:center;gap:6px}
|
||||
.gs-ico{width:14px;text-align:center;font-size:10px;color:var(--ink-3);flex-shrink:0;cursor:help}
|
||||
.gs-lbl{flex:1;font-family:var(--font-terminal);font-size:10px;color:var(--ink-3);letter-spacing:.04em}
|
||||
.gs-val{font-family:var(--font-mono);font-size:11px;color:var(--ink-2);white-space:nowrap;flex-shrink:0}
|
||||
.gs-bar{position:relative;height:9px;border-radius:3px;background:var(--bg-1);
|
||||
border:1px solid var(--border-1);overflow:hidden;box-shadow:inset 0 1px 2px rgba(0,0,0,.3)}
|
||||
.gs-fill{height:100%;border-radius:2px;background:var(--ok);transition:width .3s}
|
||||
.gs-fill.w{background:var(--warn)}.gs-fill.e{background:var(--err)}
|
||||
.gs-gloss{position:absolute;inset:0;background:linear-gradient(180deg,rgba(255,255,255,.12),transparent);pointer-events:none}
|
||||
.tile-foot{font-family:var(--font-terminal);font-size:10px;color:var(--ink-4);
|
||||
display:flex;align-items:center;justify-content:space-between;user-select:none}
|
||||
.tile-foot-info{display:flex;align-items:center;gap:5px;min-width:0;overflow:hidden}
|
||||
|
||||
+42
-19
@@ -36,6 +36,28 @@ const Grid = (() => {
|
||||
return '';
|
||||
}
|
||||
|
||||
function renderGaugeRow(faIcon, tip, label, pct, fillClass, valStr, extra) {
|
||||
const standard = (App.serverConfig?.gauge_type ?? 'compact') === 'standard';
|
||||
if (standard) {
|
||||
return `<div class="gs-row">
|
||||
<div class="gs-header">
|
||||
<span class="gs-ico" data-tip="${tip}"><i class="fa-solid fa-${faIcon}"></i></span>
|
||||
<span class="gs-lbl">${label}</span>
|
||||
<span class="gs-val">${valStr}</span>${extra || ''}
|
||||
</div>
|
||||
<div class="gs-bar">
|
||||
<div class="gs-fill ${fillClass}" style="width:${(pct ?? 0).toFixed(1)}%"></div>
|
||||
<div class="gs-gloss"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
return `<div class="g-row">
|
||||
<div class="g-ico" data-tip="${tip}"><i class="fa-solid fa-${faIcon}"></i></div>
|
||||
<div class="g-bar"><div class="g-fill ${fillClass}" style="width:${(pct ?? 0).toFixed(0)}%"></div></div>
|
||||
<span class="g-val">${valStr}</span>${extra || ''}
|
||||
</div>`;
|
||||
}
|
||||
|
||||
function renderTile(agent, metrics) {
|
||||
const id = agent.id;
|
||||
const sc = statusClass(agent);
|
||||
@@ -77,24 +99,19 @@ const Grid = (() => {
|
||||
<div class="t-led ${ledClass(agent.status)}"></div>
|
||||
</div>
|
||||
<div class="tile-gauges">
|
||||
<div class="g-row">
|
||||
<div class="g-ico" data-tip="CPU"><i class="fa-solid fa-microchip"></i></div>
|
||||
<div class="g-bar"><div class="g-fill ${offline ? '' : gFill(cpu ?? 0)}"
|
||||
style="width:${offline ? 0 : (cpu ?? 0).toFixed(0)}%"></div></div>
|
||||
<span class="g-val">${offline ? '—' : fmtPct(cpu)}</span>
|
||||
</div>
|
||||
<div class="g-row">
|
||||
<div class="g-ico" data-tip="RAM"><i class="fa-solid fa-memory"></i></div>
|
||||
<div class="g-bar"><div class="g-fill ${offline ? '' : gFill(memPct ?? 0)}"
|
||||
style="width:${offline ? 0 : (memPct ?? 0).toFixed(0)}%"></div></div>
|
||||
<span class="g-val">${offline ? '—' : (metrics?.memory_used && metrics?.memory_total ? fmt(metrics.memory_used) + '/' + fmt(metrics.memory_total) : '—')}</span>
|
||||
</div>
|
||||
<div class="g-row">
|
||||
<div class="g-ico" data-tip="Disque"><i class="fa-solid fa-hard-drive"></i></div>
|
||||
<div class="g-bar"><div class="g-fill ${offline ? '' : (diskPct >= (App.serverConfig?.warn_disk ?? 75) ? 'w' : '')}"
|
||||
style="width:${offline ? 0 : (diskPct ?? 0).toFixed(0)}%"></div></div>
|
||||
<span class="g-val">${offline ? '—' : (metrics?.hdd_used && metrics?.hdd_total ? fmt(metrics.hdd_used) + '/' + fmt(metrics.hdd_total) : '—')}</span>${smartIco}
|
||||
</div>
|
||||
${renderGaugeRow('microchip', 'CPU', 'CPU',
|
||||
offline ? 0 : (cpu ?? 0),
|
||||
offline ? '' : gFill(cpu ?? 0),
|
||||
offline ? '—' : fmtPct(cpu))}
|
||||
${renderGaugeRow('memory', 'RAM', 'MÉMOIRE',
|
||||
offline ? 0 : (memPct ?? 0),
|
||||
offline ? '' : gFill(memPct ?? 0),
|
||||
offline ? '—' : (metrics?.memory_used && metrics?.memory_total ? fmt(metrics.memory_used) + '/' + fmt(metrics.memory_total) : '—'))}
|
||||
${renderGaugeRow('hard-drive', 'Disque', 'DISQUE',
|
||||
offline ? 0 : (diskPct ?? 0),
|
||||
offline ? '' : (diskPct >= (App.serverConfig?.warn_disk ?? 75) ? 'w' : ''),
|
||||
offline ? '—' : (metrics?.hdd_used && metrics?.hdd_total ? fmt(metrics.hdd_used) + '/' + fmt(metrics.hdd_total) : '—'),
|
||||
smartIco)}
|
||||
</div>
|
||||
<div class="tile-foot">
|
||||
<span class="tile-foot-info">
|
||||
@@ -173,6 +190,12 @@ const Grid = (() => {
|
||||
document.getElementById('stat-err').textContent = err;
|
||||
}
|
||||
|
||||
function rerenderAll() {
|
||||
const grid = document.getElementById('agents-grid');
|
||||
if (!grid) return;
|
||||
grid.innerHTML = [..._agents.values()].map(({ agent, metrics }) => renderTile(agent, metrics)).join('');
|
||||
}
|
||||
|
||||
function removeAgent(id) {
|
||||
_agents.delete(id);
|
||||
const el = document.getElementById('tile-' + id);
|
||||
@@ -191,5 +214,5 @@ const Grid = (() => {
|
||||
updateStats();
|
||||
}
|
||||
|
||||
return { refresh, update, updateStatus, removeAgent, getAgent, fmt, fmtPct };
|
||||
return { refresh, update, updateStatus, removeAgent, rerenderAll, getAgent, fmt, fmtPct };
|
||||
})();
|
||||
|
||||
@@ -312,6 +312,11 @@ const Popups = (() => {
|
||||
<input type="range" class="scfg-slider" min="10" max="18" value="${cfg.font_size ?? 13}"
|
||||
oninput="this.nextElementSibling.textContent=this.value+'px'" id="s-font">
|
||||
<span class="scfg-val">${cfg.font_size ?? 13}px</span></div>
|
||||
<div class="scfg-row"><label>Type de jauge</label>
|
||||
<select class="scfg-select" id="s-gauge-type">
|
||||
<option value="compact" ${(cfg.gauge_type ?? 'compact') === 'compact' ? 'selected' : ''}>Compact</option>
|
||||
<option value="standard" ${(cfg.gauge_type ?? 'compact') === 'standard' ? 'selected' : ''}>Standard</option>
|
||||
</select></div>
|
||||
</div>
|
||||
<div style="display:flex;flex-direction:column;gap:8px">
|
||||
<div class="scfg-sec-title">SEUILS D'ALERTE</div>
|
||||
@@ -372,11 +377,14 @@ const Popups = (() => {
|
||||
warn_disk: parseInt(document.getElementById('s-warn-disk')?.value ?? 75),
|
||||
retention_days: parseInt(document.getElementById('s-retention')?.value ?? 30),
|
||||
chart_duration_min: parseInt(document.getElementById('s-chart-dur')?.value ?? 30),
|
||||
gauge_type: document.getElementById('s-gauge-type')?.value ?? 'compact',
|
||||
};
|
||||
const prevGaugeType = App.serverConfig?.gauge_type ?? 'compact';
|
||||
await API.putServerConfig(cfg);
|
||||
App.serverConfig = cfg;
|
||||
document.documentElement.style.setProperty('--tile-min', cfg.tile_min_width + 'px');
|
||||
document.body.style.fontSize = cfg.font_size + 'px';
|
||||
if (cfg.gauge_type !== prevGaugeType) Grid.rerenderAll();
|
||||
hideSrvCfg();
|
||||
}
|
||||
|
||||
|
||||
@@ -88,6 +88,7 @@ type ServerConfig struct {
|
||||
Notifications bool `json:"notifications"`
|
||||
PopupDetailW int `json:"popup_detail_w"`
|
||||
PopupDetailH int `json:"popup_detail_h"`
|
||||
GaugeType string `json:"gauge_type"`
|
||||
}
|
||||
|
||||
func DefaultAgentConfig() *AgentConfig {
|
||||
@@ -111,6 +112,7 @@ func DefaultServerConfig() ServerConfig {
|
||||
RetentionDays: 30, ChartDurationMin: 30,
|
||||
HideOffline: false, Notifications: true,
|
||||
PopupDetailW: 560, PopupDetailH: 600,
|
||||
GaugeType: "compact",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user