webui: organize config page with subtabs
This commit is contained in:
@@ -34,6 +34,7 @@ body{margin:0;background:var(--bg);color:var(--text);font-family:-apple-system,B
|
||||
h1{font-size:21px;margin:0}.sub{color:var(--muted);font-size:13px;margin-top:4px}
|
||||
.pill{border:1px solid var(--line);border-radius:999px;padding:7px 10px;color:var(--muted);font-size:12px;white-space:nowrap}
|
||||
.tabs{position:fixed;left:0;right:0;bottom:0;background:#080c11;border-top:1px solid var(--line);display:grid;grid-template-columns:repeat(3,1fr);z-index:10}
|
||||
.subtabs{display:flex;gap:8px;overflow-x:auto;padding:2px 0 12px;margin-bottom:4px}.subtabbtn{width:auto;white-space:nowrap;border:1px solid var(--line);background:#101722;color:var(--muted);padding:10px 12px;border-radius:999px;font-size:13px}.subtabbtn.active{background:#1f2b3c;color:var(--text);border-color:#3b536f}.configSubpage{display:none}.configSubpage.active{display:block}
|
||||
.tabbtn{border:0;border-radius:0;background:#080c11;color:var(--muted);padding:13px 8px;font-weight:800}
|
||||
.tabbtn.active{color:var(--text);background:#111923}
|
||||
.page{display:none}.page.active{display:block}
|
||||
@@ -173,141 +174,182 @@ input{width:100%;border:1px solid var(--line);border-radius:12px;padding:12px;ba
|
||||
</div>
|
||||
|
||||
<div id="configPage" class="page">
|
||||
<div class="grid">
|
||||
<section class="card span12 configIntro">
|
||||
<div class="configGroupHeader">
|
||||
<div>
|
||||
<div class="configGroupTitle">Settings</div>
|
||||
<div class="configGroupHelp">Configure the Cargo ESP32 controller. The Cargo ESP remains the source of truth for relays, sensors, WiFi, and AP settings.</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<div class="subtabs">
|
||||
<button id="configTab-general" class="subtabbtn active" onclick="showConfigSubtab('general')">General</button>
|
||||
<button id="configTab-wifi" class="subtabbtn" onclick="showConfigSubtab('wifi')">WiFi / AP</button>
|
||||
<button id="configTab-relays" class="subtabbtn" onclick="showConfigSubtab('relays')">Relays</button>
|
||||
<button id="configTab-temps" class="subtabbtn" onclick="showConfigSubtab('temps')">Temperatures</button>
|
||||
<button id="configTab-bms" class="subtabbtn" onclick="showConfigSubtab('bms')">BMS</button>
|
||||
<button id="configTab-maintenance" class="subtabbtn" onclick="showConfigSubtab('maintenance')">Maintenance</button>
|
||||
</div>
|
||||
|
||||
<section class="card span12">
|
||||
<div class="configGroupHeader">
|
||||
<div>
|
||||
<div class="configGroupTitle">Access Point</div>
|
||||
<div class="configGroupHelp">This is the local camp network hosted by the Cargo ESP32. Phones and the dashboard connect here when no Starlink/home WiFi is available.</div>
|
||||
<div id="config-general" class="configSubpage active">
|
||||
<div class="grid">
|
||||
<section class="card span12 configIntro">
|
||||
<div class="configGroupHeader">
|
||||
<div>
|
||||
<div class="configGroupTitle">Settings</div>
|
||||
<div class="configGroupHelp">Configure the Cargo ESP32 controller. The Cargo ESP remains the source of truth for relays, sensors, WiFi, and AP settings.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list">
|
||||
<div class="row"><span class="muted">Current AP</span><span class="v" id="apCurrentSsid">--</span></div>
|
||||
<div class="row"><span class="muted">Security</span><span class="v" id="apSecurity">--</span></div>
|
||||
<input id="apSsidInput" placeholder="AP SSID, example: Xterra-Camp">
|
||||
<div class="inputHelp">SSID must be 1-32 characters.</div>
|
||||
<input id="apPasswordInput" placeholder="New AP password" type="password">
|
||||
<div class="inputHelp">Password must be 8-63 characters. The current password is never displayed.</div>
|
||||
<div class="inlineActions">
|
||||
<button onclick="toggleApPassword()">Show / Hide Password</button>
|
||||
<button class="on" onclick="saveApConfig()">Save AP Settings</button>
|
||||
</div>
|
||||
<div class="configWarning">Saving AP settings restarts the access point. Your phone may disconnect and need to reconnect to the new SSID/password. Dashboard auto-migration is planned but not implemented yet.</div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section class="card span12">
|
||||
<div class="configGroupHeader">
|
||||
<div>
|
||||
<div class="configGroupTitle">Home / Starlink WiFi</div>
|
||||
<div class="configGroupHelp">Optional client networks the Cargo ESP can join. Lower priority number is tried first. The AP remains available for local access.</div>
|
||||
<section class="card span12">
|
||||
<div class="configGroupHeader">
|
||||
<div>
|
||||
<div class="configGroupTitle">General</div>
|
||||
<div class="configGroupHelp">Controller identity and general display settings.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list">
|
||||
<input id="w1s" placeholder="Network 1 SSID">
|
||||
<input id="w1p" placeholder="Network 1 password" type="password">
|
||||
<input id="w1r" placeholder="Network 1 priority" inputmode="numeric">
|
||||
<input id="w2s" placeholder="Network 2 SSID">
|
||||
<input id="w2p" placeholder="Network 2 password" type="password">
|
||||
<input id="w2r" placeholder="Network 2 priority" inputmode="numeric">
|
||||
<input id="w3s" placeholder="Network 3 SSID">
|
||||
<input id="w3p" placeholder="Network 3 password" type="password">
|
||||
<input id="w3r" placeholder="Network 3 priority" inputmode="numeric">
|
||||
<button onclick="saveWifi()">Save WiFi</button>
|
||||
<button onclick="connectWifi()">Connect Now</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card span12">
|
||||
<div class="configGroupHeader">
|
||||
<div>
|
||||
<div class="configGroupTitle">Relay Outputs</div>
|
||||
<div class="configGroupHelp">Rename relay outputs. IDs stay fixed for API/UART compatibility.</div>
|
||||
<div class="list">
|
||||
<input id="deviceNameInput" placeholder="Device name">
|
||||
<button class="on" onclick="saveDeviceConfig()">Save Device Name</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list" id="relayConfigList"></div>
|
||||
<button onclick="saveRelayConfig()">Save Relay Names</button>
|
||||
</section>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="card span12">
|
||||
<div class="configGroupHeader">
|
||||
<div>
|
||||
<div class="configGroupTitle">Temperature Assignment</div>
|
||||
<div class="configGroupHelp">Scan probes, then assign a discovered sensor to a configured temp slot.</div>
|
||||
<div id="config-wifi" class="configSubpage">
|
||||
<div class="grid">
|
||||
<section class="card span12">
|
||||
<div class="configGroupHeader">
|
||||
<div>
|
||||
<div class="configGroupTitle">Access Point</div>
|
||||
<div class="configGroupHelp">This is the local camp network hosted by the Cargo ESP32. Phones and the dashboard connect here when no Starlink/home WiFi is available.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list">
|
||||
<button onclick="scanTemps()">Scan Temp Probes</button>
|
||||
<div id="tempScanResults" class="list"></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card span12">
|
||||
<div class="label">Temperature Sensor Config</div>
|
||||
<div class="sub">Set how many temp sensors are enabled and rename each slot.</div>
|
||||
<div class="list">
|
||||
<input id="tempEnabledCount" placeholder="Enabled sensor count, 0-8" inputmode="numeric">
|
||||
<div id="tempConfigList" class="list"></div>
|
||||
<button onclick="saveTempConfig()">Save Temperature Config</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card span12">
|
||||
<div class="configGroupHeader">
|
||||
<div>
|
||||
<div class="configGroupTitle">Device</div>
|
||||
<div class="configGroupHelp">Controller identity and BMS connection settings.</div>
|
||||
<div class="list">
|
||||
<div class="row"><span class="muted">Current AP</span><span class="v" id="apCurrentSsid">--</span></div>
|
||||
<div class="row"><span class="muted">Security</span><span class="v" id="apSecurity">--</span></div>
|
||||
<input id="apSsidInput" placeholder="AP SSID, example: Xterra-Camp">
|
||||
<div class="inputHelp">SSID must be 1-32 characters.</div>
|
||||
<input id="apPasswordInput" placeholder="New AP password" type="password">
|
||||
<div class="inputHelp">Password must be 8-63 characters. The current password is never displayed.</div>
|
||||
<div class="inlineActions">
|
||||
<button onclick="toggleApPassword()">Show / Hide Password</button>
|
||||
<button class="on" onclick="saveApConfig()">Save AP Settings</button>
|
||||
</div>
|
||||
<div class="configWarning">Saving AP settings restarts the access point. Your phone may disconnect and need to reconnect to the new SSID/password. Dashboard auto-migration is planned but not implemented yet.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list">
|
||||
<input id="deviceNameInput" placeholder="Device name">
|
||||
<button onclick="saveDeviceConfig()">Save Device Name</button>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section class="card span12">
|
||||
<div class="label">BMS Config</div>
|
||||
<div class="sub">Use this for initial setup, bench mode, or replacing the battery/BMS.</div>
|
||||
<div class="list">
|
||||
<input id="bmsNameInput" placeholder="BMS name">
|
||||
<input id="bmsAddressInput" placeholder="BMS BLE address">
|
||||
<input id="bmsAddressTypeInput" placeholder="Address type: public or random">
|
||||
<div class="btnrow">
|
||||
<button onclick="saveBmsFullConfig()">Save BMS</button>
|
||||
<button class="off" onclick="setBmsEnabled(false)">Disable BMS</button>
|
||||
<section class="card span12">
|
||||
<div class="configGroupHeader">
|
||||
<div>
|
||||
<div class="configGroupTitle">Home / Starlink WiFi</div>
|
||||
<div class="configGroupHelp">Optional client networks the Cargo ESP can join. Lower priority number is tried first. The AP remains available for local access.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list">
|
||||
<input id="w1s" placeholder="Network 1 SSID">
|
||||
<input id="w1p" placeholder="Network 1 password" type="password">
|
||||
<input id="w1r" placeholder="Network 1 priority" inputmode="numeric">
|
||||
<input id="w2s" placeholder="Network 2 SSID">
|
||||
<input id="w2p" placeholder="Network 2 password" type="password">
|
||||
<input id="w2r" placeholder="Network 2 priority" inputmode="numeric">
|
||||
<input id="w3s" placeholder="Network 3 SSID">
|
||||
<input id="w3p" placeholder="Network 3 password" type="password">
|
||||
<input id="w3r" placeholder="Network 3 priority" inputmode="numeric">
|
||||
<button onclick="saveWifi()">Save WiFi</button>
|
||||
<button onclick="connectWifi()">Connect Now</button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="config-relays" class="configSubpage">
|
||||
<div class="grid">
|
||||
<section class="card span12">
|
||||
<div class="configGroupHeader">
|
||||
<div>
|
||||
<div class="configGroupTitle">Relay Outputs</div>
|
||||
<div class="configGroupHelp">Rename relay outputs. IDs stay fixed for API/UART compatibility.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list" id="relayConfigList"></div>
|
||||
<button onclick="saveRelayConfig()">Save Relay Names</button>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="config-temps" class="configSubpage">
|
||||
<div class="grid">
|
||||
<section class="card span12">
|
||||
<div class="configGroupHeader">
|
||||
<div>
|
||||
<div class="configGroupTitle">Temperature Assignment</div>
|
||||
<div class="configGroupHelp">Scan probes, then assign discovered sensors to configured temp slots.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list">
|
||||
<button onclick="scanTemps()">Scan Temp Probes</button>
|
||||
<div id="tempScanResults" class="list"></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card span12">
|
||||
<div class="configGroupHeader">
|
||||
<div>
|
||||
<div class="configGroupTitle">Temperature Slots</div>
|
||||
<div class="configGroupHelp">Enable only the probes you use. Pick one weather sensor for the top badge.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list">
|
||||
<input id="tempEnabledCount" placeholder="Enabled temp count" inputmode="numeric">
|
||||
<div id="tempConfigList" class="list"></div>
|
||||
<button onclick="saveTempConfig()">Save Temperature Config</button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="config-bms" class="configSubpage">
|
||||
<div class="grid">
|
||||
<section class="card span12">
|
||||
<div class="configGroupHeader">
|
||||
<div>
|
||||
<div class="configGroupTitle">BMS</div>
|
||||
<div class="configGroupHelp">JBD/Xiaoxiang BLE settings. Do not change these unless pairing a different BMS.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list">
|
||||
<input id="bmsNameInput" placeholder="BMS name">
|
||||
<input id="bmsAddressInput" placeholder="BMS BLE address">
|
||||
<input id="bmsAddressTypeInput" placeholder="Address type: public or random">
|
||||
<button class="on" onclick="saveBmsFullConfig()">Save BMS Config</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card span12">
|
||||
<div class="configGroupHeader">
|
||||
<div>
|
||||
<div class="configGroupTitle">BMS Polling</div>
|
||||
<div class="configGroupHelp">Enable or disable BMS polling without changing BLE pairing details.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row"><span class="muted">BMS Polling</span><span class="v" id="bmsEnabledText">--</span></div>
|
||||
<div class="btnrow">
|
||||
<button onclick="setBmsEnabled(true)">Enable BMS</button>
|
||||
<button class="off" onclick="setBmsEnabled(false)">Disable BMS</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="card span12">
|
||||
<div class="label">System Actions</div>
|
||||
<div class="sub">Use carefully. Factory reset clears install-specific configuration.</div>
|
||||
<div class="btnrow">
|
||||
<button class="off" onclick="factoryReset()">Factory Reset</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card span12">
|
||||
<div class="label">System</div>
|
||||
<div class="row"><span class="muted">Firmware</span><span class="v" id="fw">--</span></div>
|
||||
<div class="row"><span class="muted">Uptime</span><span class="v" id="uptime">--</span></div>
|
||||
<div class="row"><span class="muted">AP IP</span><span class="v" id="apIp">--</span></div>
|
||||
</section>
|
||||
<div id="config-maintenance" class="configSubpage">
|
||||
<div class="grid">
|
||||
<section class="card span12">
|
||||
<div class="configGroupHeader">
|
||||
<div>
|
||||
<div class="configGroupTitle">Maintenance</div>
|
||||
<div class="configGroupHelp">Reset and recovery actions. These can disrupt the controller.</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="off" onclick="factoryReset()">Factory Reset Config</button>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tabs">
|
||||
<button class="tabbtn active" onclick="showTab('overview')">Overview</button>
|
||||
@@ -474,6 +516,15 @@ function batteryTimeInfo(b){
|
||||
|
||||
return {label:"Battery time", value:"Idle"};
|
||||
}
|
||||
function showConfigSubtab(name){
|
||||
["general","wifi","relays","temps","bms","maintenance"].forEach(t=>{
|
||||
const page=$("config-"+t);
|
||||
const btn=$("configTab-"+t);
|
||||
if(page) page.classList.toggle("active",t===name);
|
||||
if(btn) btn.classList.toggle("active",t===name);
|
||||
});
|
||||
}
|
||||
|
||||
function showTab(name){
|
||||
["overview","battery","config"].forEach(t=>{
|
||||
$(t+"Page").classList.toggle("active",t===name);
|
||||
|
||||
Reference in New Issue
Block a user