diff --git a/data/index.html b/data/index.html index 3786e88..ce17042 100644 --- a/data/index.html +++ b/data/index.html @@ -6,14 +6,30 @@ Konfiguration +
-

Konfiguration

-
+
+
+ +

+
+ +
+
+ + +

Konfiguration

Verbindung diff --git a/data/load-data.js b/data/load-data.js index 2c18434..1ec35a7 100644 --- a/data/load-data.js +++ b/data/load-data.js @@ -1,25 +1,27 @@ +import { + showLoadingScreen, + showError, + hideLoadingScreen, +} from "./loading-screen.js"; + const form = document.querySelector("form"); -async function loadData() { - try { - const req = await fetch("/config", { - method: "GET", - }); - if (!req.ok) { - throw new Error(`Response status: ${req.status}`); - } - - const json = await req.json(); - console.log(json); - return json; - } catch (error) { - console.log(error); - return null; +export async function loadData(timeout = null) { + const req = await fetch("/config", { + method: "GET", + signal: timeout !== null ? AbortSignal.timeout(timeout) : undefined, + }); + if (!req.ok) { + throw new Error(`Response status: ${req.status}`); } + + const json = await req.json(); + console.log(json); + return json; } export function writeDataToInput(data) { - console.log("write data", typeof data); + console.log("write data"); for (const [key, value] of Object.entries(data)) { const element = document.querySelector(`[name=${key}]`); console.log(key, element); @@ -34,7 +36,12 @@ export function writeDataToInput(data) { form.dispatchEvent(new Event("change", { bubbles: true })); } -const data = await loadData(); -if (data !== null) { +showLoadingScreen("Konfiguration wird geladen..."); +try { + const data = await loadData(); + hideLoadingScreen(); writeDataToInput(data); +} catch (error) { + console.log(error.message); + showError("Die Konfiguration konnte nicht geladen werden."); } diff --git a/data/loading-screen.js b/data/loading-screen.js new file mode 100644 index 0000000..4b04769 --- /dev/null +++ b/data/loading-screen.js @@ -0,0 +1,40 @@ +const form = document.querySelector("form"); +const loadingScreen = document.querySelector(".loading-screen"); +const loadingMsg = loadingScreen.querySelector("h2"); +const spinner = loadingScreen.querySelector(".spinner"); +const reloadBtn = loadingScreen.querySelector(".reload"); + +export function showLoadingScreen(msg) { + hide(form, reloadBtn); + show(loadingScreen, spinner); + loadingMsg.classList.remove("error"); + loadingMsg.textContent = msg; +} + +export function showError(msg) { + showLoadingScreen(msg); + loadingMsg.innerHTML += + "
Stelle sicher, dass du mit dem DMX-Interface verbunden bist und die IP-Adresse stimmt."; + show(reloadBtn); + hide(spinner); + loadingMsg.classList.add("error"); +} + +export function hideLoadingScreen() { + hide(loadingScreen, reloadBtn); + show(form); + loadingMsg.classList.remove("error"); + loadingMsg.textContent = ""; +} + +function show(...elements) { + for (const element of elements) { + element.classList.remove("hidden"); + } +} + +function hide(...elements) { + for (const element of elements) { + element.classList.add("hidden"); + } +} diff --git a/data/reset.js b/data/reset.js index 7a68957..c34c41f 100644 --- a/data/reset.js +++ b/data/reset.js @@ -1,4 +1,4 @@ -import { writeDataToInput } from "/load-data.js"; +import { updateConfig } from "/submit.js"; const form = document.querySelector("form"); @@ -9,22 +9,8 @@ form.addEventListener("reset", async (event) => { "Sicher, dass du alle Einstellungen zurücksetzen möchtest?" ); if (ok) { - reset(); - } -}); - -async function reset() { - try { - const res = await fetch("/config", { + updateConfig({ method: "DELETE", }); - if (!res.ok) { - throw new Error(`Response status: ${res.status}`); - } - - const json = await res.json(); - writeDataToInput(json); - } catch (error) { - console.error(error.message); } -} +}); diff --git a/data/style.css b/data/style.css index 8d3dde2..7cce882 100644 --- a/data/style.css +++ b/data/style.css @@ -1,6 +1,7 @@ :root { --color-primary: #087e8b; --color-on-primary: white; + --color-background: #222; --color-danger: #fa2b58; } @@ -14,7 +15,7 @@ body { } main { - background-color: #222; + background-color: var(--color-background); max-width: 700px; padding: 8px max(5%, 8px); margin: 0 auto; @@ -45,7 +46,7 @@ label { input, select { width: clamp(200px, 100%, 400px); - background-color: #222; + background-color: var(--color-background); color: white; border: 1px solid white; border-radius: 8px; @@ -78,7 +79,7 @@ button[type="reset"] { } .hidden { - display: none; + display: none !important; } label.switch { @@ -136,3 +137,61 @@ label.switch input:checked + .slider::before { justify-content: center; gap: 8px; } + +.loading-screen { + display: grid; + justify-content: center; +} + +h2.error { + color: var(--color-danger); +} + +button.reload { + display: block; + margin: 0 auto; +} + +.spinner-container { + width: min(max-content, 100%); +} + +.spinner { + position: relative; + margin: 10px auto; + background: conic-gradient(transparent 150deg, var(--color-primary)); + --outer-diameter: 50px; + width: var(--outer-diameter); + height: var(--outer-diameter); + border-radius: 50%; + + animation-name: spin; + animation-duration: 1s; + animation-iteration-count: infinite; + animation-timing-function: linear; +} + +.spinner::after { + position: absolute; + content: ""; + display: block; + --spinner-border: 5px; + top: var(--spinner-border); + left: var(--spinner-border); + + --inner-diameter: calc(var(--outer-diameter) - 2 * var(--spinner-border)); + width: var(--inner-diameter); + height: var(--inner-diameter); + + background-color: var(--color-background); + border-radius: 50%; +} + +@keyframes spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} diff --git a/data/submit.js b/data/submit.js index 8759386..0fdbda8 100644 --- a/data/submit.js +++ b/data/submit.js @@ -1,3 +1,10 @@ +import { loadData, writeDataToInput } from "./load-data.js"; +import { + showLoadingScreen, + hideLoadingScreen, + showError, +} from "./loading-screen.js"; + const form = document.querySelector("form"); function parseValue(input) { @@ -31,25 +38,35 @@ form.addEventListener("submit", (event) => { }, {}); console.log(data); - putData(data); + updateConfig({ + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(data), + }); }); -async function putData(data) { +export async function updateConfig(fetchOptions) { + showLoadingScreen("Konfiguration anwenden und ESP neustarten..."); + try { - const res = await fetch("/config", { - method: "PUT", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(data), - }); + const res = await fetch("/config", fetchOptions); if (!res.ok) { throw new Error(`Response status: ${res.status}`); } - const json = await res.json(); - console.log(json); + // wait for the esp to restart + const delay = new Promise((resolve) => + setTimeout(() => resolve(), 500) + ); + await delay; + + const data = await loadData(30 * 1000); + writeDataToInput(data); + hideLoadingScreen(); } catch (error) { console.error(error.message); + showError(error.message); } }