Declutter control diagnostics sections

This commit is contained in:
seo
2026-06-22 17:26:52 +09:00
parent 5476e3f795
commit 39388e5eb2
3 changed files with 106 additions and 61 deletions
+26 -2
View File
@@ -50,6 +50,9 @@
dmesgToggle: $('#dmesgToggle'),
dmesgOutput: $('#dmesgOutput'),
dmesgMeta: $('#dmesgMeta'),
secondaryChartDetails: $('#secondaryChartDetails'),
processDetails: $('#processDetails'),
diagnosticDetails: $('#diagnosticDetails'),
};
const state = {
@@ -122,6 +125,7 @@
batteryV: 'Battery V',
batterySoc: 'Battery SOC',
sensorHistory: 'Sensor History',
detailCharts: 'Detail Charts',
temperature: 'Temperature',
rp1Temp: 'RP1 Temp',
fanEfficiency: 'Fan Efficiency',
@@ -137,6 +141,8 @@
connected: 'Connected',
inactive: 'Inactive',
systemNotice: 'System Notice',
processDetails: 'Process Details',
diagnostics: 'Diagnostics',
noticeHistory: 'Notice History',
noNoticeHistory: 'No system notice history.',
haNotifyHistory: 'HA Notify History',
@@ -250,6 +256,7 @@
batteryV: '배터리 전압',
batterySoc: '배터리 SOC',
sensorHistory: '센서 이력',
detailCharts: '상세 차트',
temperature: '온도',
rp1Temp: 'RP1 온도',
fanEfficiency: '팬 효율',
@@ -265,6 +272,8 @@
connected: '연결 시간',
inactive: '비활성',
systemNotice: '시스템 알림',
processDetails: '프로세스 상세',
diagnostics: '진단',
noticeHistory: '알림 이력',
noNoticeHistory: '시스템 알림 이력이 없습니다.',
haNotifyHistory: 'HA 알림 이력',
@@ -1002,8 +1011,9 @@
function renderSpikeHistory(rows = []) {
if (!els.spikeLogList) return;
els.spikeLogList.innerHTML = rows.length
? rows.map((row, index) => {
const visibleRows = rows.slice(0, 3);
els.spikeLogList.innerHTML = visibleRows.length
? visibleRows.map((row, index) => {
const processText = spikeProcessText(row);
return `
@@ -1388,6 +1398,17 @@
chart('batteryVoltageChart', 'BATTERYV', rows, 'battery_voltage', '#14b8a6', 'V', dynamicScale(rows, 'battery_voltage', { minSpan: 0.2, padding: 0.06 }));
}
function resizeChartsSoon() {
window.setTimeout(() => {
Object.values(state.charts).forEach(chartInstance => {
if (chartInstance && typeof chartInstance.resize === 'function') {
chartInstance.resize();
chartInstance.update('none');
}
});
}, 80);
}
function render(data) {
renderTop(data);
renderSystemStatus(data);
@@ -1616,6 +1637,9 @@
els.dmesgToggle?.addEventListener('click', () => {
setDmesgOpen(!state.dmesgOpen);
});
[els.secondaryChartDetails, els.processDetails, els.diagnosticDetails].forEach(node => {
node?.addEventListener('toggle', resizeChartsSoon);
});
els.rebootBtn?.addEventListener('click', () => {
requestReboot();
});
+70 -52
View File
@@ -104,8 +104,9 @@ html[data-theme="light"] .btn.secondary{background:#d9e2ef;color:#172033}html[da
.btn:disabled{opacity:.55;cursor:not-allowed}
.status-list{display:grid;gap:10px}.status-row{display:grid;grid-template-columns:112px minmax(0,1fr);gap:12px;align-items:baseline;padding:10px 12px;background:var(--card2);border-radius:14px}.status-key{color:var(--sub);font-size:13px}.status-value{overflow:visible;white-space:normal;word-break:break-word;font-variant-numeric:tabular-nums}
.table-wrap{max-width:100%;overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;border-radius:16px;border:1px solid var(--line)}.wifi-table{width:100%;min-width:1080px;table-layout:fixed;border-collapse:collapse}.wifi-table th,.wifi-table td{padding:11px 13px;border-bottom:1px solid rgba(128,145,170,.18);text-align:left;font-size:14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.wifi-table th{position:sticky;top:0;background:var(--table-head);z-index:1;font-weight:500}.wifi-table tr:hover{background:rgba(128,145,170,.09)}.wifi-table .col-band{width:72px}.wifi-table .col-host{width:240px}.wifi-table .col-ip{width:132px}.wifi-table .col-mac{width:170px}.wifi-table .col-signal{width:100px}.wifi-table .col-rate{width:120px}.wifi-table .col-time{width:130px}
.chart-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:14px}.chart-box{height:280px;background:var(--input);border:1px solid rgba(84,101,128,.58);border-radius:16px;padding:12px 12px 18px}.chart-box h3{margin:0 0 8px;color:var(--sub);font-size:13px}.chart-canvas{position:relative;height:calc(100% - 27px);min-height:0}.chart-canvas canvas{width:100%!important;height:100%!important}
.resource-card{margin-top:18px}.resource-head{display:flex;align-items:baseline;justify-content:space-between;gap:12px;margin-bottom:16px}.resource-head h2{margin:0}.baseline-pill{color:var(--sub);font-size:12px;font-variant-numeric:tabular-nums;text-align:right;white-space:nowrap}.spike-log-box{margin-top:16px}.spike-log-box h3{margin:0 0 9px;color:var(--text);font-size:14px;font-weight:500}.spike-log-list{display:grid;gap:8px;max-height:260px;overflow:auto;padding-right:4px}.spike-log-item{display:grid;gap:4px;padding:10px 12px;border:1px solid var(--notice-border);background:var(--notice-bg);border-radius:12px}.spike-log-item.latest{border:1px solid var(--notice-border-strong);background:var(--notice-bg-strong);box-shadow:0 0 0 1px var(--notice-border) inset;}.spike-log-item.alert{border-color:rgba(255,95,87,.58);background:rgba(150,38,38,.18)}.spike-log-item.alert strong{color:#ffb4ad}.spike-log-item strong{font-size:13px;font-weight:500;color:var(--notice-title)}.spike-log-item span{font-size:12px;color:var(--notice-copy);font-variant-numeric:tabular-nums}.spike-log-empty{padding:10px 12px;border-radius:12px;background:var(--card2);color:var(--sub);font-size:13px}.service-list{display:grid;gap:10px;max-height:520px;overflow:auto;padding-right:4px}.service-item{border:1px solid var(--line);border-radius:12px;background:var(--card2);padding:12px;display:grid;gap:9px}.service-head{display:flex;justify-content:space-between;gap:10px;align-items:flex-start}.service-title{display:grid;gap:3px;min-width:0}.service-name{font-size:14px;color:var(--text);font-weight:600;word-break:break-word}.service-desc,.service-meta{font-size:12px;color:var(--sub);font-variant-numeric:tabular-nums;word-break:break-word}.service-state{border:1px solid var(--line);border-radius:999px;padding:4px 9px;font-size:12px;color:var(--sub);white-space:nowrap}.service-state.active{color:#bbf7d0;border-color:rgba(34,197,94,.35);background:rgba(22,163,74,.14)}.service-state.failed{color:#fecaca;border-color:rgba(239,68,68,.4);background:rgba(185,28,28,.16)}.service-log{margin:0;max-height:160px;overflow:auto;border:1px solid var(--line);border-radius:10px;background:var(--code-bg);color:var(--mono-text);padding:10px;font:11px/1.45 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;white-space:pre-wrap;word-break:break-word}.dmesg-head{display:flex;align-items:center;justify-content:space-between;gap:10px}.dmesg-meta{font-size:12px;color:var(--sub);font-variant-numeric:tabular-nums}.dmesg-log{margin:10px 0 0;max-height:420px;overflow:auto;border:1px solid var(--line);border-radius:12px;background:var(--code-bg);color:var(--mono-text);padding:12px;font:12px/1.45 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;white-space:pre-wrap;word-break:break-word}.dmesg-log[hidden]{display:none}
.chart-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:14px}.chart-box{height:280px;background:var(--input);border:1px solid rgba(84,101,128,.58);border-radius:16px;padding:12px 12px 18px}.chart-box h3{margin:0 0 8px;color:var(--sub);font-size:13px}.chart-canvas{position:relative;height:calc(100% - 27px);min-height:0}.chart-canvas canvas{width:100%!important;height:100%!important}.chart-secondary{margin-top:14px}
.details-panel{border:1px solid rgba(84,101,128,.52);border-radius:16px;background:rgba(128,145,170,.06);padding:0;margin-top:14px;overflow:hidden}.details-panel>summary{cursor:pointer;list-style:none;display:flex;align-items:center;justify-content:space-between;gap:12px;min-height:48px;padding:0 14px;color:var(--text);font-weight:500}.details-panel>summary::-webkit-details-marker{display:none}.details-panel>summary::after{content:"+";display:grid;place-items:center;width:24px;height:24px;border:1px solid var(--line);border-radius:999px;color:var(--sub);font-weight:700}.details-panel[open]>summary::after{content:"-"}.details-body{padding:0 14px 14px}.section-note{margin:0;color:var(--sub);font-size:12px}
.resource-card{margin-top:18px}.resource-head{display:flex;align-items:baseline;justify-content:space-between;gap:12px;margin-bottom:12px}.resource-head h2{margin:0}.baseline-pill{color:var(--sub);font-size:12px;font-variant-numeric:tabular-nums;text-align:right;white-space:nowrap}.spike-log-box{margin-top:16px}.spike-log-box h3{margin:0 0 9px;color:var(--text);font-size:14px;font-weight:500}.spike-log-list{display:grid;gap:8px;max-height:260px;overflow:auto;padding-right:4px}.spike-log-list.compact{max-height:180px}.spike-log-item{display:grid;gap:4px;padding:10px 12px;border:1px solid var(--notice-border);background:var(--notice-bg);border-radius:12px}.spike-log-item.latest{border:1px solid var(--notice-border-strong);background:var(--notice-bg-strong);box-shadow:0 0 0 1px var(--notice-border) inset;}.spike-log-item.alert{border-color:rgba(255,95,87,.58);background:rgba(150,38,38,.18)}.spike-log-item.alert strong{color:#ffb4ad}.spike-log-item strong{font-size:13px;font-weight:500;color:var(--notice-title)}.spike-log-item span{font-size:12px;color:var(--notice-copy);font-variant-numeric:tabular-nums}.spike-log-empty{padding:10px 12px;border-radius:12px;background:var(--card2);color:var(--sub);font-size:13px}.service-list{display:grid;gap:10px;max-height:520px;overflow:auto;padding-right:4px}.service-item{border:1px solid var(--line);border-radius:12px;background:var(--card2);padding:12px;display:grid;gap:9px}.service-head{display:flex;justify-content:space-between;gap:10px;align-items:flex-start}.service-title{display:grid;gap:3px;min-width:0}.service-name{font-size:14px;color:var(--text);font-weight:600;word-break:break-word}.service-desc,.service-meta{font-size:12px;color:var(--sub);font-variant-numeric:tabular-nums;word-break:break-word}.service-state{border:1px solid var(--line);border-radius:999px;padding:4px 9px;font-size:12px;color:var(--sub);white-space:nowrap}.service-state.active{color:#bbf7d0;border-color:rgba(34,197,94,.35);background:rgba(22,163,74,.14)}.service-state.failed{color:#fecaca;border-color:rgba(239,68,68,.4);background:rgba(185,28,28,.16)}.service-log{margin:0;max-height:160px;overflow:auto;border:1px solid var(--line);border-radius:10px;background:var(--code-bg);color:var(--mono-text);padding:10px;font:11px/1.45 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;white-space:pre-wrap;word-break:break-word}.dmesg-head{display:flex;align-items:center;justify-content:space-between;gap:10px}.dmesg-meta{font-size:12px;color:var(--sub);font-variant-numeric:tabular-nums}.dmesg-log{margin:10px 0 0;max-height:420px;overflow:auto;border:1px solid var(--line);border-radius:12px;background:var(--code-bg);color:var(--mono-text);padding:12px;font:12px/1.45 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;white-space:pre-wrap;word-break:break-word}.dmesg-log[hidden]{display:none}
.resource-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px}.resource-box{min-width:0}.resource-box h3{margin:0 0 9px;color:var(--sub);font-size:14px;font-weight:500}.resource-table{width:100%;min-width:620px;table-layout:fixed;border-collapse:collapse;border:1px solid var(--line);border-radius:14px;overflow:hidden}.resource-table th,.resource-table td{padding:9px 10px;border-bottom:1px solid rgba(128,145,170,.18);background:var(--input);text-align:left;font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.resource-table th{background:var(--table-head);color:var(--sub);font-weight:500}.resource-table .pid{width:72px}.resource-table .metric{width:82px}.resource-table .service{width:150px}.resource-table .cmd{width:auto}
.notice{position:fixed;right:20px;bottom:20px;min-width:220px;max-width:420px;padding:14px 16px;border-radius:14px;font-weight:500;background:var(--table-head);color:var(--text);border:1px solid var(--line);box-shadow:var(--shadow);z-index:99}.notice:empty{display:none}.notice[data-type=success]{border-color:rgba(53,196,107,.5)}.notice[data-type=error]{border-color:rgba(255,95,87,.5)}
.dialog-layer{position:fixed;inset:0;display:none;align-items:center;justify-content:center;padding:22px;background:rgba(4,7,12,.68);backdrop-filter:blur(8px);z-index:120}.dialog-layer[data-open="1"]{display:flex}.dialog-box{width:min(430px,100%);border:1px solid rgba(84,101,128,.78);border-radius:20px;background:var(--card);box-shadow:0 24px 70px rgba(0,0,0,.42);padding:20px}.dialog-box h3{margin:0 0 8px;font-size:19px;font-weight:500}.dialog-message{margin:0 0 16px;color:var(--sub);line-height:1.5;white-space:pre-wrap}.dialog-input{width:100%;height:48px;margin-bottom:14px;border-radius:14px;border:1px solid var(--line);background:var(--input);color:var(--text);padding:0 14px;outline:none}.dialog-input:focus{outline:2px solid rgba(59,130,246,.65);outline-offset:2px}.dialog-actions{display:flex;justify-content:flex-end;gap:10px}.dialog-actions .btn{min-width:84px}.dialog-actions .btn.red{background:#c62828}
@@ -201,16 +202,23 @@ html[data-theme="light"] .btn.secondary{background:#d9e2ef;color:#172033}html[da
<section class="stack">
<div class="card">
<h2 data-i18n="sensorHistory">Sensor History</h2>
<div class="chart-grid">
<div class="chart-box"><h3 data-i18n="temperature">Temperature</h3><div class="chart-canvas"><canvas id="tempChart"></canvas></div></div>
<div class="chart-box"><h3 data-i18n="rp1Temp">RP1 Temp</h3><div class="chart-canvas"><canvas id="rp1TempChart"></canvas></div></div>
<div class="chart-grid">
<div class="chart-box"><h3 data-i18n="temperature">Temperature</h3><div class="chart-canvas"><canvas id="tempChart"></canvas></div></div>
<div class="chart-box"><h3 data-i18n="fanRpm">Fan RPM</h3><div class="chart-canvas"><canvas id="fanRpmChart"></canvas></div></div>
<div class="chart-box"><h3 data-i18n="fanEfficiency">Fan Efficiency</h3><div class="chart-canvas"><canvas id="fanEfficiencyChart"></canvas></div></div>
<div class="chart-box"><h3 data-i18n="cpuWatt">CPU Watt</h3><div class="chart-canvas"><canvas id="cpuWattChart"></canvas></div></div>
<div class="chart-box"><h3 data-i18n="batterySoc">Battery SOC</h3><div class="chart-canvas"><canvas id="batterySocChart"></canvas></div></div>
<div class="chart-box"><h3 data-i18n="remaining">Remaining</h3><div class="chart-canvas"><canvas id="remainingChart"></canvas></div></div>
<div class="chart-box"><h3 data-i18n="batteryVoltage">Battery Voltage</h3><div class="chart-canvas"><canvas id="batteryVoltageChart"></canvas></div></div>
</div>
<details class="details-panel" id="secondaryChartDetails">
<summary data-i18n="detailCharts">Detail Charts</summary>
<div class="details-body">
<div class="chart-grid chart-secondary">
<div class="chart-box"><h3 data-i18n="rp1Temp">RP1 Temp</h3><div class="chart-canvas"><canvas id="rp1TempChart"></canvas></div></div>
<div class="chart-box"><h3 data-i18n="fanEfficiency">Fan Efficiency</h3><div class="chart-canvas"><canvas id="fanEfficiencyChart"></canvas></div></div>
<div class="chart-box"><h3 data-i18n="cpuWatt">CPU Watt</h3><div class="chart-canvas"><canvas id="cpuWattChart"></canvas></div></div>
<div class="chart-box"><h3 data-i18n="remaining">Remaining</h3><div class="chart-canvas"><canvas id="remainingChart"></canvas></div></div>
</div>
</div>
</details>
</div>
<div class="card">
@@ -241,58 +249,68 @@ html[data-theme="light"] .btn.secondary{background:#d9e2ef;color:#172033}html[da
<h2 data-i18n="systemNotice">System Notice</h2>
<div id="noticeBaseline" class="baseline-pill">Baseline: -</div>
</div>
<div class="resource-grid">
<div class="resource-box">
<h3>CPU</h3>
<div class="table-wrap">
<table class="resource-table">
<colgroup><col class="pid"><col class="metric"><col class="service"><col class="cmd"></colgroup>
<thead><tr><th>PID</th><th>CPU</th><th>Service</th><th>Command</th></tr></thead>
<tbody id="processCpuTable"><tr><td colspan="4">loading...</td></tr></tbody>
</table>
</div>
</div>
<div class="resource-box">
<h3>Memory</h3>
<div class="table-wrap">
<table class="resource-table">
<colgroup><col class="pid"><col class="metric"><col class="service"><col class="cmd"></colgroup>
<thead><tr><th>PID</th><th>MEM</th><th>Service</th><th>Command</th></tr></thead>
<tbody id="processMemoryTable"><tr><td colspan="4">loading...</td></tr></tbody>
</table>
</div>
</div>
</div>
<div class="spike-log-box">
<h3 data-i18n="noticeHistory">Notice History</h3>
<div id="spikeLogList" class="spike-log-list">
<h3 data-i18n="noticeHistory">Notice History</h3>
<div id="spikeLogList" class="spike-log-list compact">
<div class="spike-log-empty" data-i18n="noNoticeHistory">No system notice history.</div>
</div>
</div>
<div class="spike-log-box">
<h3 data-i18n="customServices">Custom Services</h3>
<div id="customServiceList" class="service-list">
<div class="spike-log-empty" data-i18n="noCustomServices">No custom services.</div>
<details class="details-panel" id="processDetails">
<summary data-i18n="processDetails">Process Details</summary>
<div class="details-body">
<div class="resource-grid">
<div class="resource-box">
<h3>CPU</h3>
<div class="table-wrap">
<table class="resource-table">
<colgroup><col class="pid"><col class="metric"><col class="service"><col class="cmd"></colgroup>
<thead><tr><th>PID</th><th>CPU</th><th>Service</th><th>Command</th></tr></thead>
<tbody id="processCpuTable"><tr><td colspan="4">loading...</td></tr></tbody>
</table>
</div>
</div>
<div class="resource-box">
<h3>Memory</h3>
<div class="table-wrap">
<table class="resource-table">
<colgroup><col class="pid"><col class="metric"><col class="service"><col class="cmd"></colgroup>
<thead><tr><th>PID</th><th>MEM</th><th>Service</th><th>Command</th></tr></thead>
<tbody id="processMemoryTable"><tr><td colspan="4">loading...</td></tr></tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</details>
<div class="spike-log-box">
<h3 data-i18n="haNotifyHistory">HA Notify History</h3>
<div id="haNotifyList" class="spike-log-list">
<div class="spike-log-empty" data-i18n="noHaNotifyHistory">No HA notify history.</div>
</div>
</div>
<details class="details-panel" id="diagnosticDetails">
<summary data-i18n="diagnostics">Diagnostics</summary>
<div class="details-body">
<div class="spike-log-box">
<h3 data-i18n="customServices">Custom Services</h3>
<div id="customServiceList" class="service-list">
<div class="spike-log-empty" data-i18n="noCustomServices">No custom services.</div>
</div>
</div>
<div class="spike-log-box">
<div class="dmesg-head">
<h3>dmesg</h3>
<button class="btn secondary" id="dmesgToggle" type="button" data-i18n="show">Show</button>
<div class="spike-log-box">
<h3 data-i18n="haNotifyHistory">HA Notify History</h3>
<div id="haNotifyList" class="spike-log-list">
<div class="spike-log-empty" data-i18n="noHaNotifyHistory">No HA notify history.</div>
</div>
</div>
<div class="spike-log-box">
<div class="dmesg-head">
<h3>dmesg</h3>
<button class="btn secondary" id="dmesgToggle" type="button" data-i18n="show">Show</button>
</div>
<div class="dmesg-meta" id="dmesgMeta">/tmp/dmesg.log</div>
<pre class="dmesg-log" id="dmesgOutput" hidden></pre>
</div>
</div>
<div class="dmesg-meta" id="dmesgMeta">/tmp/dmesg.log</div>
<pre class="dmesg-log" id="dmesgOutput" hidden></pre>
</div>
</details>
</section>
</div>
<div id="notice" class="notice"></div>
@@ -307,7 +325,7 @@ html[data-theme="light"] .btn.secondary{background:#d9e2ef;color:#172033}html[da
</div>
</div>
</div>
<script src="/assets/app.js?v=20260621_services1"></script>
<script src="/assets/app.js?v=20260622_declutter1"></script>
<script src="/assets/wakelock.js?v=20260607_prefs1"></script>
<?php endif; ?>
</body>