feat(web): city presets for station settings
Add a City preset dropdown (Astana, Karaganda, Almaty, Bishkek, Tashkent, Yekaterinburg, Omsk, Novosibirsk, Krasnoyarsk, Moscow, Saint Petersburg) that fills altitude, coordinates and time zone from average values. Manual entry and Custom remain; the matching preset is auto-selected on load when coordinates match. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -185,7 +185,11 @@ static const char INDEX_HTML[] PROGMEM = R"HTML(
|
|||||||
<summary>Station settings <span class="caret">Adjust</span></summary>
|
<summary>Station settings <span class="caret">Adjust</span></summary>
|
||||||
<hr class="rule">
|
<hr class="rule">
|
||||||
<div class="form">
|
<div class="form">
|
||||||
<div class="grid2" style="margin-top:18px">
|
<div style="margin-top:18px">
|
||||||
|
<label>City preset</label>
|
||||||
|
<select id="s-city"></select>
|
||||||
|
</div>
|
||||||
|
<div class="grid2" style="margin-top:14px">
|
||||||
<div><label>Altitude · metres</label><input id="s-alt" type="number" step="1"></div>
|
<div><label>Altitude · metres</label><input id="s-alt" type="number" step="1"></div>
|
||||||
<div><label>Time zone</label><select id="s-tz"></select></div>
|
<div><label>Time zone</label><select id="s-tz"></select></div>
|
||||||
<div><label>Latitude</label><input id="s-lat" type="number" step="0.0001"></div>
|
<div><label>Latitude</label><input id="s-lat" type="number" step="0.0001"></div>
|
||||||
@@ -382,15 +386,53 @@ function updateSetHand(){
|
|||||||
function tzLabel(min){var s=min<0?"-":"+";var a=Math.abs(min);var h=Math.floor(a/60);var m=a%60;return "UTC"+s+h+(m?(":"+(m<10?"0":"")+m):"");}
|
function tzLabel(min){var s=min<0?"-":"+";var a=Math.abs(min);var h=Math.floor(a/60);var m=a%60;return "UTC"+s+h+(m?(":"+(m<10?"0":"")+m):"");}
|
||||||
function buildTz(){var sel=document.getElementById("s-tz");for(var m=-720;m<=840;m+=30){var o=document.createElement("option");o.value=m;o.textContent=tzLabel(m);sel.appendChild(o);}}
|
function buildTz(){var sel=document.getElementById("s-tz");for(var m=-720;m<=840;m+=30){var o=document.createElement("option");o.value=m;o.textContent=tzLabel(m);sel.appendChild(o);}}
|
||||||
|
|
||||||
|
// City presets: approximate average elevation (m), coordinates and UTC offset (min).
|
||||||
|
var CITIES=[
|
||||||
|
{n:"Astana", alt:347, lat:51.1694, lon:71.4491, tz:300},
|
||||||
|
{n:"Karaganda", alt:553, lat:49.8047, lon:73.1094, tz:300},
|
||||||
|
{n:"Almaty", alt:848, lat:43.2220, lon:76.8512, tz:300},
|
||||||
|
{n:"Bishkek", alt:800, lat:42.8746, lon:74.5698, tz:360},
|
||||||
|
{n:"Tashkent", alt:455, lat:41.2995, lon:69.2401, tz:300},
|
||||||
|
{n:"Yekaterinburg", alt:237, lat:56.8389, lon:60.6057, tz:300},
|
||||||
|
{n:"Omsk", alt:87, lat:54.9885, lon:73.3242, tz:360},
|
||||||
|
{n:"Novosibirsk", alt:150, lat:55.0084, lon:82.9357, tz:420},
|
||||||
|
{n:"Krasnoyarsk", alt:137, lat:56.0153, lon:92.8932, tz:420},
|
||||||
|
{n:"Moscow", alt:156, lat:55.7558, lon:37.6173, tz:180},
|
||||||
|
{n:"Saint Petersburg",alt:3, lat:59.9311, lon:30.3609, tz:180}
|
||||||
|
];
|
||||||
|
function setTz(min){
|
||||||
|
var tz=document.getElementById("s-tz"); tz.value=String(min);
|
||||||
|
if(parseInt(tz.value,10)!==min){var o=document.createElement("option");o.value=min;o.textContent=tzLabel(min);tz.appendChild(o);tz.value=String(min);}
|
||||||
|
}
|
||||||
|
function buildCities(){
|
||||||
|
var sel=document.getElementById("s-city");
|
||||||
|
var o0=document.createElement("option"); o0.value="-1"; o0.textContent="Custom / manual entry"; sel.appendChild(o0);
|
||||||
|
CITIES.forEach(function(c,i){
|
||||||
|
var o=document.createElement("option"); o.value=i;
|
||||||
|
o.textContent=c.n+" · "+c.alt+" m · "+tzLabel(c.tz); sel.appendChild(o);
|
||||||
|
});
|
||||||
|
sel.addEventListener("change",function(){
|
||||||
|
var i=parseInt(sel.value,10); if(i<0) return;
|
||||||
|
var c=CITIES[i];
|
||||||
|
document.getElementById("s-alt").value=c.alt;
|
||||||
|
document.getElementById("s-lat").value=c.lat;
|
||||||
|
document.getElementById("s-lon").value=c.lon;
|
||||||
|
setTz(c.tz);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async function loadSettings(){
|
async function loadSettings(){
|
||||||
try{
|
try{
|
||||||
var s=await (await fetch("/api/settings")).json();
|
var s=await (await fetch("/api/settings")).json();
|
||||||
document.getElementById("s-alt").value=s.altitude;
|
document.getElementById("s-alt").value=s.altitude;
|
||||||
var tz=document.getElementById("s-tz"); tz.value=String(s.tz);
|
setTz(s.tz);
|
||||||
if(parseInt(tz.value,10)!==s.tz){var o=document.createElement("option");o.value=s.tz;o.textContent=tzLabel(s.tz);tz.appendChild(o);tz.value=String(s.tz);}
|
|
||||||
document.getElementById("s-lat").value=s.lat;
|
document.getElementById("s-lat").value=s.lat;
|
||||||
document.getElementById("s-lon").value=s.lon;
|
document.getElementById("s-lon").value=s.lon;
|
||||||
document.getElementById("coords").innerHTML=Number(s.lat).toFixed(2)+"°N, "+Number(s.lon).toFixed(2)+"°E";
|
document.getElementById("coords").innerHTML=Number(s.lat).toFixed(2)+"°N, "+Number(s.lon).toFixed(2)+"°E";
|
||||||
|
// Auto-select a matching city preset, else "Custom".
|
||||||
|
var ci=-1;
|
||||||
|
for(var k=0;k<CITIES.length;k++){ if(Math.abs(CITIES[k].lat-s.lat)<0.02 && Math.abs(CITIES[k].lon-s.lon)<0.02){ ci=k; break; } }
|
||||||
|
document.getElementById("s-city").value=String(ci);
|
||||||
}catch(e){}
|
}catch(e){}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -413,6 +455,7 @@ document.getElementById("save").addEventListener("click", async function(){
|
|||||||
|
|
||||||
buildGauge();
|
buildGauge();
|
||||||
buildTz();
|
buildTz();
|
||||||
|
buildCities();
|
||||||
loadSettings();
|
loadSettings();
|
||||||
refresh();
|
refresh();
|
||||||
setInterval(refresh,15000);
|
setInterval(refresh,15000);
|
||||||
|
|||||||
Reference in New Issue
Block a user