From efe7ac65cdfd4a5a7b073f0360c4492c730c1649 Mon Sep 17 00:00:00 2001 From: jotaen4tinypilot <83721279+jotaen4tinypilot@users.noreply.github.com> Date: Tue, 16 Jul 2024 15:22:43 +0200 Subject: [PATCH] WiFi dialog: add dialog to the UI (#1813) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Related https://github.com/tiny-pilot/tinypilot/issues/131, part (d). Stacked on https://github.com/tiny-pilot/tinypilot/pull/1812. This PR adds a new dialog “Wi-Fi” to the “System→Network” menu, which makes the Wi-Fi feature available to end-users. Summary of the discussion below: - We made the wording so that it’s clear that we only store the WiFi credentials, but we don’t verify whether they are actually accepted by the WiFi router, or whether the WiFi is reachable at all. For further clarification, we also added a success state to the dialog. - In a subsequent PR, we’ll turn the “country code” free text field into a dropdown, to make it easier for users to enter their correct and applicable value. Review
on CodeApprove --------- Co-authored-by: Jan Heuermann --- app/static/css/style.css | 3 +- app/static/js/app.js | 7 + app/static/js/controllers.js | 69 ++++ app/templates/custom-elements/menu-bar.html | 5 + .../custom-elements/wifi-dialog.html | 349 ++++++++++++++++++ app/templates/index.html | 3 + 6 files changed, 435 insertions(+), 1 deletion(-) create mode 100644 app/templates/custom-elements/wifi-dialog.html diff --git a/app/static/css/style.css b/app/static/css/style.css index d7b2af8c3..edf308ba9 100644 --- a/app/static/css/style.css +++ b/app/static/css/style.css @@ -112,7 +112,8 @@ input[type="password"] { box-shadow: inset 0 0 0.2rem 0 rgba(0, 0, 0, 0.15); } -input[type="text"].monospace { +input[type="text"].monospace, +input[type="password"].monospace { font-family: "Overpass Mono", monospace; /* Since the monospace font has different characteristics than the regular font, we need to set the height here explicitly. In the end, the input diff --git a/app/static/js/app.js b/app/static/js/app.js index 86f944322..84667befc 100644 --- a/app/static/js/app.js +++ b/app/static/js/app.js @@ -320,6 +320,13 @@ menuBar.addEventListener("change-hostname-dialog-requested", () => { document.getElementById("change-hostname-overlay").show(); document.getElementById("change-hostname-dialog").initialize(); }); +menuBar.addEventListener("wifi-dialog-requested", () => { + // Note: we have to call `initialize()` after `show()`, to ensure that the + // dialog is able to focus the main input element. + // See https://github.com/tiny-pilot/tinypilot/issues/1770 + document.getElementById("wifi-overlay").show(); + document.getElementById("wifi-dialog").initialize(); +}); menuBar.addEventListener("fullscreen-requested", () => { document.getElementById("remote-screen").fullscreen = true; }); diff --git a/app/static/js/controllers.js b/app/static/js/controllers.js index f49a33b7f..a67c552ad 100644 --- a/app/static/js/controllers.js +++ b/app/static/js/controllers.js @@ -194,6 +194,75 @@ export async function changeHostname(newHostname) { .then(() => newHostname); } +export async function getNetworkStatus() { + return fetch("/api/network/status", { + method: "GET", + mode: "same-origin", + cache: "no-cache", + redirect: "error", + }) + .then(processJsonResponse) + .then((response) => { + ["ethernet", "wifi"].forEach((field) => { + // eslint-disable-next-line no-prototype-builtins + if (!response.hasOwnProperty(field)) { + throw new ControllerError(`Missing expected ${field} field`); + } + }); + return response; + }); +} + +export async function getWifiSettings() { + return fetch("/api/network/settings/wifi", { + method: "GET", + mode: "same-origin", + cache: "no-cache", + redirect: "error", + }) + .then(processJsonResponse) + .then((response) => { + ["countryCode", "ssid"].forEach((field) => { + // eslint-disable-next-line no-prototype-builtins + if (!response.hasOwnProperty(field)) { + throw new ControllerError(`Missing expected ${field} field`); + } + }); + return response; + }); +} + +export async function enableWifi(countryCode, ssid, psk) { + return fetch("/api/network/settings/wifi", { + method: "PUT", + mode: "same-origin", + cache: "no-cache", + redirect: "error", + headers: { + "Content-Type": "application/json", + "X-CSRFToken": getCsrfToken(), + }, + body: JSON.stringify({ countryCode, ssid, psk }), + }) + .then(processJsonResponse) + .then(() => true); +} + +export async function disableWifi() { + return fetch("/api/network/settings/wifi", { + method: "DELETE", + mode: "same-origin", + cache: "no-cache", + redirect: "error", + headers: { + "Content-Type": "application/json", + "X-CSRFToken": getCsrfToken(), + }, + }) + .then(processJsonResponse) + .then(() => true); +} + export async function checkStatus(baseURL = "") { return fetch(baseURL + "/api/status", { method: "GET", diff --git a/app/templates/custom-elements/menu-bar.html b/app/templates/custom-elements/menu-bar.html index a72aefa2d..85d350089 100644 --- a/app/templates/custom-elements/menu-bar.html +++ b/app/templates/custom-elements/menu-bar.html @@ -229,6 +229,11 @@ >Hostname +