From 1e13258bc97e1d81ba70111fe56d25d803085507 Mon Sep 17 00:00:00 2001 From: Kroese Date: Sun, 21 Jan 2024 18:35:55 +0100 Subject: [PATCH] feat: Dynamic page content (#585) --- readme.md | 2 +- src/install.sh | 4 +- src/network.sh | 4 +- src/print.sh | 2 + src/reset.sh | 8 +-- web/css/style.css | 154 ++++++++++++++++++++++++++++++++++++++++++++ web/img/favicon.svg | 1 + web/index.html | 22 +++++-- web/js/script.js | 130 +++++++++++++++++++++++++++++++++++++ web/style.css | 59 ----------------- 10 files changed, 311 insertions(+), 75 deletions(-) create mode 100644 web/css/style.css create mode 100644 web/img/favicon.svg create mode 100644 web/js/script.js delete mode 100644 web/style.css diff --git a/readme.md b/readme.md index 1f6c1508..f0927482 100644 --- a/readme.md +++ b/readme.md @@ -58,7 +58,7 @@ docker run -it --rm -p 5000:5000 --device=/dev/kvm --cap-add NET_ADMIN --stop-ti - Start the container and get some coffee. - - Connect to port 5000 of the container in your web browser. + - Connect to [port 5000](http://localhost:5000) of the container in your web browser. - Wait until DSM is ready, choose an username and password, and you will be taken to the desktop. diff --git a/src/install.sh b/src/install.sh index a26e95c3..0caea360 100644 --- a/src/install.sh +++ b/src/install.sh @@ -174,8 +174,8 @@ fi rm -rf "$TMP" && mkdir -p "$TMP" -MSG="Downloading $BASE.pat..." -info "Install: $MSG" && html "$MSG" +info "Install: Downloading $BASE.pat..." +html "Install: Downloading DSM from Synology..." PAT="/$BASE.pat" rm -f "$PAT" diff --git a/src/network.sh b/src/network.sh index 601694d2..2d52fb0c 100644 --- a/src/network.sh +++ b/src/network.sh @@ -254,8 +254,8 @@ if [[ "$DHCP" == [Yy1]* ]]; then # Configuration for DHCP IP configureDHCP - MSG="Please wait while discovering IP..." - html "$MSG" "2000" + MSG="Booting DSM instance..." + html "$MSG" else diff --git a/src/print.sh b/src/print.sh index d2ddd1a8..068f1f1a 100644 --- a/src/print.sh +++ b/src/print.sh @@ -7,6 +7,7 @@ info () { printf "%b%s%b" "\E[1;34m❯ \E[1;36m" "$1" "\E[0m\n" >&2; } error () { printf "%b%s%b" "\E[1;31m❯ " "ERROR: $1" "\E[0m\n" >&2; } file="/run/shm/dsm.url" +info="/run/shm/msg.html" page="/run/shm/index.html" address="/run/shm/qemu.ip" shutdown="/run/shm/qemu.end" @@ -80,6 +81,7 @@ if [[ "$location" != "20.20"* ]]; then HTML="${HTML/\[5\]/}" echo "$HTML" > "$page" + echo "$body" > "$info" else diff --git a/src/reset.sh b/src/reset.sh index f385ca01..2b223a31 100644 --- a/src/reset.sh +++ b/src/reset.sh @@ -29,6 +29,7 @@ echo # Helper variables STORAGE="/storage" +INFO="/dev/shm/msg.html" PAGE="/run/shm/index.html" TEMPLATE="/var/www/index.html" FOOTER1="$APP for Docker v$(${body/.../}

" fi - local timeout="4999" - [ -n "${2:-}" ] && timeout="$2" - local script="" - [[ "$timeout" == "0" ]] && script="" + [ -n "${2:-}" ] && script="$2" || script="" local HTML HTML=$(<"$TEMPLATE") @@ -143,6 +142,7 @@ html() HTML="${HTML/\[5\]/$FOOTER2}" echo "$HTML" > "$PAGE" + echo "$body" > "$INFO" return 0 } diff --git a/web/css/style.css b/web/css/style.css new file mode 100644 index 00000000..d17bfa28 --- /dev/null +++ b/web/css/style.css @@ -0,0 +1,154 @@ +body { + color: white; + background-color: #125bdb; + font-family: Verdana, Arial, sans-serif; +} + +#content { + text-align: center; + padding: 20px; + margin-top: 50px; +} + +footer { + width: 98%; + position: fixed; + bottom: 0px; + height: 40px; + text-align: center; + color: #0c8aeb; +} + +#empty { + height: 40px; + /* Same height as footer */ +} + +a, +a:hover, +a:active, +a:visited { + color: white; +} + +footer a:link, +footer a:visited, +footer a:active { color: #0c8aeb; } +footer a:hover { color: #73e6ff; } + +.loading:after { + content: " ."; + animation: dots 1s steps(5, end) infinite; +} + +@keyframes dots { + + 0%, + 20% { + color: rgba(0, 0, 0, 0); + text-shadow: 0.25em 0 0 rgba(0, 0, 0, 0), 0.5em 0 0 rgba(0, 0, 0, 0); + } + + 40% { + color: white; + text-shadow: 0.25em 0 0 rgba(0, 0, 0, 0), 0.5em 0 0 rgba(0, 0, 0, 0); + } + + 60% { + text-shadow: 0.25em 0 0 white, 0.5em 0 0 rgba(0, 0, 0, 0); + } + + 80%, + 100% { + text-shadow: 0.25em 0 0 white, 0.5em 0 0 white; + } +} + +.spinner_LWk7 { + animation: spinner_GWy6 1.2s linear infinite, spinner_BNNO 1.2s linear infinite +} + +.spinner_yOMU { + animation: spinner_GWy6 1.2s linear infinite, spinner_pVqn 1.2s linear infinite; + animation-delay: .15s +} + +.spinner_KS4S { + animation: spinner_GWy6 1.2s linear infinite, spinner_6uKB 1.2s linear infinite; + animation-delay: .3s +} + +.spinner_zVee { + animation: spinner_GWy6 1.2s linear infinite, spinner_Qw4x 1.2s linear infinite; + animation-delay: .45s +} + +@keyframes spinner_GWy6 { + + 0%, + 50% { + width: 9px; + height: 9px + } + + 10% { + width: 11px; + height: 11px + } +} + +@keyframes spinner_BNNO { + + 0%, + 50% { + x: 1.5px; + y: 1.5px + } + + 10% { + x: .5px; + y: .5px + } +} + +@keyframes spinner_pVqn { + + 0%, + 50% { + x: 13.5px; + y: 1.5px + } + + 10% { + x: 12.5px; + y: .5px + } +} + +@keyframes spinner_6uKB { + + 0%, + 50% { + x: 13.5px; + y: 13.5px + } + + 10% { + x: 12.5px; + y: 12.5px + } +} + +@keyframes spinner_Qw4x { + + 0%, + 50% { + x: 1.5px; + y: 13.5px + } + + 10% { + x: .5px; + y: 12.5px + } +} diff --git a/web/img/favicon.svg b/web/img/favicon.svg new file mode 100644 index 00000000..9cbb85f0 --- /dev/null +++ b/web/img/favicon.svg @@ -0,0 +1 @@ + diff --git a/web/index.html b/web/index.html index 10a9faaf..0f10e136 100644 --- a/web/index.html +++ b/web/index.html @@ -5,22 +5,30 @@ [1] - + + [2] -
-
-

[3]

+
+
+ + + + + + +

[3]

-
+
- +
+ diff --git a/web/js/script.js b/web/js/script.js new file mode 100644 index 00000000..fc5dc0a6 --- /dev/null +++ b/web/js/script.js @@ -0,0 +1,130 @@ +var request; +var interval = 1000; + +function getInfo() { + + var url = "/msg.html"; + + try { + + if (window.XMLHttpRequest) { + request = new XMLHttpRequest(); + } else { + throw "XMLHttpRequest not available!"; + } + + request.onreadystatechange = processInfo; + request.open("GET", url, true); + request.send(); + + } catch (e) { + var err = "Error: " + e.message; + console.log(err); + setError(err); + } +} + +function processInfo() { + try { + if (request.readyState != 4) { + return true; + } + + var msg = request.responseText; + if (msg == null || msg.length == 0) { + setInfo("Booting DSM instance", true); + schedule(); + return false; + } + + var notFound = (request.status == 404); + + if (request.status == 200) { + if (msg.toLowerCase().indexOf("") !== -1) { + notFound = true; + } else { + if (msg.toLowerCase().indexOf("href=") !== -1) { + var div = document.createElement("div"); + div.innerHTML = msg; + var url = div.querySelector("a").href; + setTimeout(() => { + window.location.assign(url); + }, 3000); + setInfo(msg); + return true; + } else { + setInfo(msg); + schedule(); + return true; + } + } + } + + if (notFound) { + setInfo("Connecting to web portal", true); + reload(); + return true; + } + + setError("Error: Received statuscode " + request.status); + schedule(); + return false; + + } catch (e) { + var err = "Error: " + e.message; + console.log(err); + setError(err); + return false; + } +} + +function setInfo(msg, loading, error) { + + try { + if (msg == null || msg.length == 0) { + return false; + } + + var el = document.getElementById("spinner"); + + error = !!error; + if (!error) { + el.style.visibility = 'visible'; + } else { + el.style.visibility = 'hidden'; + } + + loading = !!loading; + if (loading) { + msg = "

" + msg + "

"; + } + + el = document.getElementById("info"); + + if (el.innerHTML != msg) { + el.innerHTML = msg; + } + + return true; + + } catch (e) { + console.log("Error: " + e.message); + return false; + } +} + +function setError(text) { + return setInfo(text, false, true); +} + +function schedule() { + setTimeout(getInfo, interval); +} + +function reload() { + setTimeout(() => { + document.location.reload(); + }, 3000); +} + +schedule(); diff --git a/web/style.css b/web/style.css deleted file mode 100644 index def18b76..00000000 --- a/web/style.css +++ /dev/null @@ -1,59 +0,0 @@ -body { - color: white; - background-color: #125bdb; - font-family: Verdana, Arial, sans-serif; -} - -#content-wrap { - text-align: center; - padding: 20px; - margin-top: 100px; -} - -#footer { - width: 98%; - position: fixed; - bottom: 0px; - height: 40px; - text-align: center; -} - -#empty-space { - height: 40px; - /* Same height as footer */ -} - -a, -a:hover, -a:active, -a:visited { - color: white; -} - -.loading:after { - content: " ."; - animation: dots 1s steps(5, end) infinite; -} - -@keyframes dots { - - 0%, - 20% { - color: rgba(0, 0, 0, 0); - text-shadow: 0.25em 0 0 rgba(0, 0, 0, 0), 0.5em 0 0 rgba(0, 0, 0, 0); - } - - 40% { - color: white; - text-shadow: 0.25em 0 0 rgba(0, 0, 0, 0), 0.5em 0 0 rgba(0, 0, 0, 0); - } - - 60% { - text-shadow: 0.25em 0 0 white, 0.5em 0 0 rgba(0, 0, 0, 0); - } - - 80%, - 100% { - text-shadow: 0.25em 0 0 white, 0.5em 0 0 white; - } -}