From 547f9a42b4d4fea3c3b3a33e8586b315f27f9b1c Mon Sep 17 00:00:00 2001 From: "Adrian A. Baumann" Date: Sat, 4 Jul 2026 20:35:28 +0200 Subject: [PATCH] Display multiple meters in tabbed interface --- src/main.cpp | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 15e8db2..f01adc2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -432,6 +432,15 @@ static void handleRoot() { if (!requireAuth()) { Serial.println("[HTTP] GET / -> 401"); return; } Serial.println("[HTTP] GET /"); String meterRows; + bool useTabs = meterCount > 1; + if (useTabs) { + meterRows += "
"; + for (int i = 0; i < meterCount; i++) { + String label = strlen(meters[i].name) > 0 ? escHtml(meters[i].name) : "Meter " + String(i); + meterRows += ""; + } + meterRows += "
"; + } for (int i = 0; i < meterCount; i++) { char maxStr[8], curStr[8]; dtostrf(meters[i].maxDuty, 1, 1, maxStr); @@ -443,7 +452,9 @@ static void handleRoot() { dtostrf(meters[i].rangeMin, 1, 1, rMinStr); dtostrf(meters[i].rangeMax, 1, 1, rMaxStr); - meterRows += "
Meter " + String(i) + ""; + if (useTabs) meterRows += "
"; + meterRows += "
"; + if (!useTabs) meterRows += "Meter " + String(i) + ""; meterRows += "
"; meterRows += "
"; meterRows += "
"; @@ -455,7 +466,9 @@ static void handleRoot() { meterRows += ""; meterRows += "" + String(curStr) + "%"; meterRows += "
"; + if (useTabs) meterRows += "
"; } + if (useTabs) meterRows += ""; String countOpts; for (int i = 1; i <= MAX_METERS; i++) { @@ -536,7 +549,11 @@ static void handleRoot() { html += ".tgl-lbl{margin-bottom:0!important;line-height:18px}.switch{position:relative;display:inline-block;width:32px;height:18px;margin-left:auto;flex-shrink:0}fieldset .row label.switch{width:32px}"; html += ".switch input{opacity:0;width:0;height:0}.slid{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background:#ccc;border-radius:18px;transition:.3s}"; html += ".slid::before{content:\"\";position:absolute;height:14px;width:14px;left:2px;top:2px;background:#fff;border-radius:50%;transition:.3s;box-shadow:0 1px 3px rgba(0,0,0,.2)}"; -html += ".switch input:checked+.slid{background:#4361ee}.switch input:checked+.slid::before{transform:translateX(14px)}"; + html += ".switch input:checked+.slid{background:#4361ee}.switch input:checked+.slid::before{transform:translateX(14px)}"; + html += ".tab-nav{display:flex;gap:4px;margin-bottom:16px;flex-wrap:wrap}"; + html += ".tab-btn{padding:8px 16px;border:1px solid #d1d5db;background:#f8f9fc;border-radius:8px 8px 0 0;cursor:pointer;font-size:13px;font-weight:600;color:#666;transition:all .2s;font-family:inherit}"; + html += ".tab-btn:hover{background:#e8eaf0}.tab-btn.active{background:#fff;border-color:#4361ee;color:#4361ee;border-bottom-color:#fff}"; + html += ".tab-panel{display:none}.tab-panel.active{display:block}"; html += "
"; html += "
logo

M1730

Configuration
"; html += "
Hostname" + String(hostname) + "
"; @@ -561,6 +578,9 @@ html += ".switch input:checked+.slid{background:#4361ee}.switch input:checked+.s html += "x.open('GET','/set?i='+this.name.match(/\\d+/)[0]+'&v='+this.value,true);x.send();"; html += "});}});"; html += "document.querySelector('select[name=meter_count]').addEventListener('change',function(){this.form.submit();});"; + if (meterCount > 1) { + html += "document.querySelectorAll('.tab-btn').forEach(function(b){b.addEventListener('click',function(){var t=this.dataset.tab;document.querySelectorAll('.tab-btn').forEach(function(x){x.classList.remove('active')});document.querySelectorAll('.tab-panel').forEach(function(x){x.classList.remove('active')});this.classList.add('active');document.querySelector('.tab-panel[data-tab=\"'+t+'\"]').classList.add('active')})});"; + } html += ""; server.send(200, "text/html", html); Serial.printf("[HTTP] GET / -> 200 (%u bytes)\n", html.length());