This commit is contained in:
148
www/settings.js
Normal file
148
www/settings.js
Normal file
@@ -0,0 +1,148 @@
|
||||
(() => {
|
||||
const el = (id) => document.getElementById(id);
|
||||
const t = (key, vars) => window.I18n?.t(key, vars) ?? key;
|
||||
|
||||
const statusEl = el("settingsStatusText");
|
||||
const inputMissionRuns = el("settingsRetentionMissionRuns");
|
||||
const inputSystemLog = el("settingsRetentionSystemLog");
|
||||
const inputErrorLogs = el("settingsRetentionErrorLogs");
|
||||
const selectLogLevel = el("settingsLogLevel");
|
||||
const gridEl = el("settingsTileGrid");
|
||||
const gridViewEl = el("settingsGridView");
|
||||
const detailViewEl = el("settingsDetailView");
|
||||
|
||||
function setStatus(text, kind = "info") {
|
||||
if (!statusEl) return;
|
||||
statusEl.textContent = text || "";
|
||||
statusEl.classList.toggle("mapsMirNote--ok", kind === "ok");
|
||||
statusEl.classList.toggle("mapsMirNote--error", kind === "error");
|
||||
}
|
||||
|
||||
const TILE_SVGS = {
|
||||
mapping: `<svg width="42" height="42" viewBox="0 0 24 24" aria-hidden="true"><path d="M4 6l6-2 4 2 6-2v14l-6 2-4-2-6 2V6z" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linejoin="round"/><path d="M10 4v14M14 6v14" fill="none" stroke="currentColor" stroke-width="1.6"/></svg>`,
|
||||
warning: `<svg width="42" height="42" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3l10 18H2L12 3z" fill="none" stroke="currentColor" stroke-width="1.6"/><path d="M12 9v5" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/><circle cx="12" cy="17" r="1" fill="currentColor"/></svg>`,
|
||||
gear: `<svg width="42" height="42" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 15.2a3.2 3.2 0 1 0 0-6.4 3.2 3.2 0 0 0 0 6.4z" fill="none" stroke="currentColor" stroke-width="1.6"/><path d="M19.4 15a8.6 8.6 0 0 0 .1-2l2-1.2-2-3.4-2.3.7a8.5 8.5 0 0 0-1.7-1L15 5h-4l-.5 2.1a8.5 8.5 0 0 0-1.7 1l-2.3-.7-2 3.4L6.6 13a8.6 8.6 0 0 0 .1 2l-2 1.2 2 3.4 2.3-.7c.5.4 1.1.7 1.7 1L11 22h4l.5-2.1c.6-.3 1.2-.6 1.7-1l2.3.7 2-3.4-2-1.2z" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linejoin="round"/></svg>`,
|
||||
battery: `<svg width="42" height="42" viewBox="0 0 24 24" aria-hidden="true"><rect x="3" y="7" width="16" height="10" rx="2" fill="none" stroke="currentColor" stroke-width="1.6"/><path d="M21 10v4" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/><path d="M6 10h8v4H6z" fill="currentColor"/></svg>`,
|
||||
calendar: `<svg width="42" height="42" viewBox="0 0 24 24" aria-hidden="true"><rect x="4" y="5" width="16" height="15" rx="2" fill="none" stroke="currentColor" stroke-width="1.6"/><path d="M8 3v4M16 3v4M4 9h16" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg>`,
|
||||
wifi: `<svg width="42" height="42" viewBox="0 0 24 24" aria-hidden="true"><path d="M2 8c5-4 15-4 20 0" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/><path d="M5 12c3.5-2.7 10.5-2.7 14 0" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/><path d="M8.5 15.5c2-1.5 5-1.5 7 0" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/><circle cx="12" cy="19" r="1.3" fill="currentColor"/></svg>`,
|
||||
};
|
||||
|
||||
const TILES = [
|
||||
{ id: "mapping", title: "settings.tile.mapping", sub: "settings.tile.mappingSub", icon: "mapping", action: "coming_soon" },
|
||||
{ id: "error_handling", title: "settings.tile.errorHandling", sub: "settings.tile.errorHandlingSub", icon: "warning", action: "coming_soon" },
|
||||
{ id: "battery", title: "settings.tile.battery", sub: "settings.tile.batterySub", icon: "battery", action: "coming_soon" },
|
||||
{ id: "wifi", title: "settings.tile.wifi", sub: "settings.tile.wifiSub", icon: "wifi", action: "coming_soon" },
|
||||
{ id: "date_time", title: "settings.tile.dateTime", sub: "settings.tile.dateTimeSub", icon: "calendar", action: "coming_soon" },
|
||||
{ id: "advanced", title: "settings.tile.advanced", sub: "settings.tile.advancedSub", icon: "gear", action: "open_logging_retention" },
|
||||
];
|
||||
|
||||
function showGrid() {
|
||||
if (gridViewEl) gridViewEl.hidden = false;
|
||||
if (detailViewEl) detailViewEl.hidden = true;
|
||||
setStatus("");
|
||||
}
|
||||
|
||||
function showDetail() {
|
||||
if (gridViewEl) gridViewEl.hidden = true;
|
||||
if (detailViewEl) detailViewEl.hidden = false;
|
||||
}
|
||||
|
||||
function renderGrid() {
|
||||
if (!gridEl) return;
|
||||
gridEl.innerHTML = TILES.map((tile) => {
|
||||
const disabled = tile.action === "coming_soon";
|
||||
return `
|
||||
<button type="button" class="settingsMirTile${disabled ? " is-disabled" : ""}" data-settings-tile="${tile.id}" ${disabled ? "disabled" : ""}>
|
||||
<div class="settingsMirTileIcon">${TILE_SVGS[tile.icon] || ""}</div>
|
||||
<div class="settingsMirTileTitle">${t(tile.title)}</div>
|
||||
<div class="settingsMirTileSub">${t(tile.sub)}</div>
|
||||
</button>`;
|
||||
}).join("");
|
||||
}
|
||||
|
||||
async function apiJson(url, opts = {}) {
|
||||
const res = await fetch(url, { credentials: "include", ...opts });
|
||||
const text = await res.text();
|
||||
let data = null;
|
||||
try {
|
||||
data = text ? JSON.parse(text) : null;
|
||||
} catch {
|
||||
data = null;
|
||||
}
|
||||
if (!res.ok) throw new Error((data && data.error) || text || res.statusText);
|
||||
return data;
|
||||
}
|
||||
|
||||
function toInt(v, fallback) {
|
||||
const n = Number(v);
|
||||
if (!Number.isFinite(n)) return fallback;
|
||||
return Math.round(n);
|
||||
}
|
||||
|
||||
async function refresh() {
|
||||
setStatus(t("settings.loading"));
|
||||
const data = await apiJson("/api/settings");
|
||||
const s = data && typeof data === "object" ? data : {};
|
||||
|
||||
if (inputMissionRuns) inputMissionRuns.value = String(toInt(s.retention_mission_runs, 2000));
|
||||
if (inputSystemLog) inputSystemLog.value = String(toInt(s.retention_system_log, 2000));
|
||||
if (inputErrorLogs) inputErrorLogs.value = String(toInt(s.retention_error_logs, 200));
|
||||
if (selectLogLevel) selectLogLevel.value = String(s.log_level || "info");
|
||||
|
||||
setStatus(t("settings.loaded"), "ok");
|
||||
}
|
||||
|
||||
async function apply() {
|
||||
const payload = {
|
||||
retention_mission_runs: toInt(inputMissionRuns?.value, 2000),
|
||||
retention_system_log: toInt(inputSystemLog?.value, 2000),
|
||||
retention_error_logs: toInt(inputErrorLogs?.value, 200),
|
||||
log_level: String(selectLogLevel?.value || "info"),
|
||||
};
|
||||
|
||||
setStatus(t("settings.saving"));
|
||||
const res = await apiJson("/api/settings", {
|
||||
method: "PUT",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
|
||||
const ok = res && typeof res === "object";
|
||||
setStatus(ok ? t("settings.saved") : t("settings.saveFailed"), ok ? "ok" : "error");
|
||||
await refresh();
|
||||
}
|
||||
|
||||
function bind() {
|
||||
renderGrid();
|
||||
gridEl?.addEventListener("click", (evt) => {
|
||||
const btn = evt.target.closest("[data-settings-tile]");
|
||||
if (!btn?.dataset.settingsTile) return;
|
||||
const tile = TILES.find((x) => x.id === btn.dataset.settingsTile);
|
||||
if (!tile) return;
|
||||
if (tile.action === "open_logging_retention") {
|
||||
showDetail();
|
||||
refresh().catch((e) => setStatus(e.message, "error"));
|
||||
}
|
||||
});
|
||||
el("settingsRefreshBtn")?.addEventListener("click", () => refresh().catch((e) => setStatus(e.message, "error")));
|
||||
el("settingsApplyBtn")?.addEventListener("click", () => apply().catch((e) => setStatus(e.message, "error")));
|
||||
el("settingsBackBtn")?.addEventListener("click", () => showGrid());
|
||||
}
|
||||
|
||||
function onPageShow() {
|
||||
showGrid();
|
||||
refresh().catch((e) => setStatus(e.message, "error"));
|
||||
}
|
||||
|
||||
function onPageHide() {}
|
||||
|
||||
window.SettingsApp = { onPageShow, onPageHide, refresh };
|
||||
|
||||
function boot() {
|
||||
bind();
|
||||
}
|
||||
|
||||
if (window.AuthApp?.isReady()) boot();
|
||||
else window.addEventListener("lm:auth-ready", boot, { once: true });
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user