diff options
Diffstat (limited to 'app.js')
| -rw-r--r-- | app.js | 160 |
1 files changed, 94 insertions, 66 deletions
@@ -1,5 +1,7 @@ (() => { - let isLoading = 0; + state = {}; + isLoading = 0; + const loading = (val) => { isLoading = val; loader.$cls(isLoading ? "" : "hidden"); @@ -7,44 +9,56 @@ loader.$click(() => loading(0)); let error = null; - function errClose() { - error = null; - app.reload(); - } - let data = {}; - function onerror(err) { - error = err; - console.error(err); + setError = (err) => { + error = String(err); app.reload(); } - function parsedata(r) { - return Object.fromEntries(r.split("\n").map(x=>x.trim()).filter(x=>x).map(x=>x.split('='))); + function errClose() { } - function cmd(url, body) { - return fetch(url, {method:body?'POST':'GET', body}) - .then(r => { - if (!r.ok){ - throw new Error(r.statusText); - } - return r.text(); - }) - .then(r => parsedata(r)); - }; - function loadconfig() { + window.onerror = (message, source, lineNumber, colno, err) => { + setError(message); + }; + window.onunhandledrejection = (event) => { + setError(event.reason); + }; + let parseini = (data) => Object.fromEntries(data.split("\n").map(x=>x.trim()).filter(x=>x).map(x=>x.split("="))); + let buildini = (data, prefix="") => entries(data).map(([k,v])=>`${prefix}${k}=${v}\n`).join(); + let resptext = r => { + if (!r.ok){ + throw new Error(r.statusText); + } + return r.text(); + }; + getconfig = () => fetch("/cgi-bin/getconfig").then(resptext).then(x => parseini(x)); + cmd = (body) => fetch("/cgi-bin/cmd",{method:"POST",body}).then(resptext); + setconfig = (data, prefix) => { loading(1); - cmd("/cgi-bin/getconfig") + cmd(buildini(data, prefix)+"save\n") + .finally(() => loading(0)) + }; + loadconfig = () => { + loading(1); + getconfig("/cgi-bin/getconfig") .then(x => { - data = x; + state = {...state, ...x}; app.reload(); }) - .catch(onerror) - .then(() => loading(0)) - } - function saveconfig(groups) { - cmd("/cgi-bin/setconfig", data) - .catch(onerror) - .then(loadconfig) + .finally(() => loading(0)); } + reboot = (data, prefix) => { + var ok = 0; + loading(1); + cmd("reboot\n") + .then(() => { + ok = 1; + }) + .finally(() => { + setTimeout(() => { + loading(0); + app.reload(); + }, ok?10000:0); + }) + }; function CErr(text) { var el = div( @@ -72,52 +86,64 @@ return routes[r](); } } + + function CSettingInput(f) { + var inp = input("text") + .$attr("id","form__"+f.id) + .$attr("name",f.id) + .$attr("required",!!f.required) + .$value(state[f.id]??null) + .$change2state(state, f.id); + if (f.pattern) { + inp.$attr("pattern", f.pattern??null); + } + if (f.invalidmsg) { + inp.oninvalid = () => inp.setCustomValidity(f.invalidmsg); + } + inp.$attr("placeholder", f.hint??""); + return tr( + td(labelfor(inp.id, f.title)).$cls("title"), + td(inp), + ); + } + + function CSettings(section) { + let s = config.sections[section]; + let form_ = form( + table(...s.fields.map(x => CSettingInput(x))).$cls("settings"), + input("submit").$value("Save") + ); + form_.onsubmit = (e) => {e.preventDefault(); setconfig({});} + return div( + h1(s.title), + form_, + ) + } + const navbar = CNav([ ["#", "Home"], - ["#/network", "Network"], - ["#/config", "Configuration"], - ["#/tools", "Tools"], + ...entries(config.sections).map(([id, x]) => [`#/${id}`, x.title]), ]); const router = CRouter({ "/": () => div( - h2("Lorem Ipsum"), - p("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. "), - p("Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."), - ), - "/network": () => div( - h1("Network settings"), + h1("Information"), table( - tr( - td("IP"), - td(input("text").$value(data["cfg.ip"])), - ), - tr( - td("MAC"), - td( - input("text").$value(data["cfg.mac"]) - .$change2state(data, "cfg.mac") - ), - ) - ).$cls("network"), - input("button").$value("Save").$click(saveconfig) + tr(td("Device:").$cls("title"), td(config.device)), + tr(td("Software Version:").$cls("title"), td(config.swVersion)), + tr(td("Hardware Version:").$cls("title"), td(config.hwVersion)), + ), + h1("Controls"), + p( + button("Reboot").$click(reboot), + ).$cls("center"), ), - "/config": () => { - return div(); - }, - "/waiting": () => { - loading(1); - setTimeout(() => { - loading(0); - }, 3000); - return div(""); - }, + ...Object.fromEntries(entries(config.sections).map(([id, _]) => [`/${id}`, () => CSettings(id)])), "": () => div( h1("Not Found"), p("The requested page is not available.") ), }); - - mount(app, (h) => { + CApp = (h) => { loading(isLoading); return [ div(error && CErr(String(error))), @@ -126,6 +152,8 @@ section(router(h)) ), ]; - }); + }; + + mount(app, CApp); loadconfig(); })() |
