webui: preserve config edits during polling
This commit is contained in:
@@ -401,6 +401,24 @@ function statusUrl(){
|
|||||||
return needsFullStatus ? api("/status") : api("/status?fields="+STATUS_FIELDS_OVERVIEW);
|
return needsFullStatus ? api("/status") : api("/status?fields="+STATUS_FIELDS_OVERVIEW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const configTouched={};
|
||||||
|
|
||||||
|
function markConfigFieldTouched(id){
|
||||||
|
configTouched[id]=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setConfigValue(id,value){
|
||||||
|
const el=$(id);
|
||||||
|
if(!el) return;
|
||||||
|
if(configTouched[id] || document.activeElement===el) return;
|
||||||
|
el.value=value ?? "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearConfigTouched(ids){
|
||||||
|
ids.forEach(id=>{delete configTouched[id];});
|
||||||
|
}
|
||||||
|
|
||||||
function mergeStatus(previous,next){
|
function mergeStatus(previous,next){
|
||||||
if(!previous) return next;
|
if(!previous) return next;
|
||||||
return Object.assign({},previous,next);
|
return Object.assign({},previous,next);
|
||||||
@@ -426,9 +444,7 @@ function renderApConfig(data){
|
|||||||
const n=data.network||{};
|
const n=data.network||{};
|
||||||
if($("apCurrentSsid")) $("apCurrentSsid").textContent=n.ap_ssid||"--";
|
if($("apCurrentSsid")) $("apCurrentSsid").textContent=n.ap_ssid||"--";
|
||||||
if($("apSecurity")) $("apSecurity").textContent=n.ap_auth||"--";
|
if($("apSecurity")) $("apSecurity").textContent=n.ap_auth||"--";
|
||||||
if($("apSsidInput") && !$("apSsidInput").dataset.touched){
|
setConfigValue("apSsidInput",n.ap_ssid||"");
|
||||||
$("apSsidInput").value=n.ap_ssid||"";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function saveApConfig(){
|
async function saveApConfig(){
|
||||||
@@ -466,6 +482,7 @@ async function saveApConfig(){
|
|||||||
|
|
||||||
$("apPasswordInput").value="";
|
$("apPasswordInput").value="";
|
||||||
alert("AP settings saved. Reconnect to the new WiFi network if this page stops updating.");
|
alert("AP settings saved. Reconnect to the new WiFi network if this page stops updating.");
|
||||||
|
clearConfigTouched(["apSsidInput","apPasswordInput"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderWeatherBadge(data){
|
function renderWeatherBadge(data){
|
||||||
@@ -699,6 +716,7 @@ async function saveDeviceConfig(){
|
|||||||
await fetch(api("/config/save"),{method:"POST"});
|
await fetch(api("/config/save"),{method:"POST"});
|
||||||
await load();
|
await load();
|
||||||
alert("Device name saved");
|
alert("Device name saved");
|
||||||
|
clearConfigTouched(["deviceNameInput"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function saveBmsFullConfig(){
|
async function saveBmsFullConfig(){
|
||||||
@@ -725,6 +743,7 @@ async function saveBmsFullConfig(){
|
|||||||
await fetch(api("/config/save"),{method:"POST"});
|
await fetch(api("/config/save"),{method:"POST"});
|
||||||
await load();
|
await load();
|
||||||
alert("BMS config saved");
|
alert("BMS config saved");
|
||||||
|
clearConfigTouched(["bmsNameInput","bmsAddressInput","bmsAddressTypeInput"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function scanTemps(){
|
async function scanTemps(){
|
||||||
@@ -896,6 +915,7 @@ async function saveTempConfig(){
|
|||||||
await fetch(api("/config/save"),{method:"POST"});
|
await fetch(api("/config/save"),{method:"POST"});
|
||||||
await load();
|
await load();
|
||||||
alert("Temperature config saved");
|
alert("Temperature config saved");
|
||||||
|
clearConfigTouched(["tempEnabledCount"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadWifiConfig(){
|
async function loadWifiConfig(){
|
||||||
@@ -921,6 +941,7 @@ async function saveWifi(){
|
|||||||
await fetch(api("/config/wifi"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({networks})});
|
await fetch(api("/config/wifi"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({networks})});
|
||||||
await loadWifiConfig();
|
await loadWifiConfig();
|
||||||
await load();
|
await load();
|
||||||
|
clearConfigTouched(["w1s","w1p","w1r","w2s","w2p","w2r","w3s","w3p","w3r"]);
|
||||||
}
|
}
|
||||||
async function connectWifi(){
|
async function connectWifi(){
|
||||||
await fetch(api("/wifi/connect"),{method:"POST"});
|
await fetch(api("/wifi/connect"),{method:"POST"});
|
||||||
@@ -937,6 +958,18 @@ async function load(){
|
|||||||
}
|
}
|
||||||
load();
|
load();
|
||||||
loadWifiConfig();
|
loadWifiConfig();
|
||||||
|
document.addEventListener("input",e=>{
|
||||||
|
if(e.target && e.target.id && (
|
||||||
|
e.target.closest("#configPage") ||
|
||||||
|
e.target.id.startsWith("w") ||
|
||||||
|
e.target.id.startsWith("ap") ||
|
||||||
|
e.target.id.startsWith("bms") ||
|
||||||
|
e.target.id.startsWith("device") ||
|
||||||
|
e.target.id.startsWith("temp")
|
||||||
|
)){
|
||||||
|
markConfigFieldTouched(e.target.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
setInterval(load,3000);
|
setInterval(load,3000);
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -460,3 +460,17 @@ def test_temp_config_lookup_is_available_to_http_handlers():
|
|||||||
helper_pos = source.index("int findTempConfigIndexById(")
|
helper_pos = source.index("int findTempConfigIndexById(")
|
||||||
first_uart_guard_pos = source.index("#if DASHBOARD_UART_ENABLED")
|
first_uart_guard_pos = source.index("#if DASHBOARD_UART_ENABLED")
|
||||||
assert helper_pos < first_uart_guard_pos
|
assert helper_pos < first_uart_guard_pos
|
||||||
|
|
||||||
|
|
||||||
|
def test_embedded_webui_preserves_config_input_while_polling():
|
||||||
|
source = firmware_source()
|
||||||
|
|
||||||
|
assert "const configTouched={};" in source
|
||||||
|
assert "function markConfigFieldTouched(id)" in source
|
||||||
|
assert "function setConfigValue(id,value)" in source
|
||||||
|
assert "document.activeElement===el" in source
|
||||||
|
assert 'document.addEventListener("input"' in source
|
||||||
|
assert 'setConfigValue("apSsidInput"' in source
|
||||||
|
assert 'setConfigValue("deviceNameInput"' in source
|
||||||
|
assert 'setConfigValue("bmsNameInput"' in source
|
||||||
|
assert 'setConfigValue("tempEnabledCount"' in source
|
||||||
|
|||||||
Reference in New Issue
Block a user