diff --git a/index.html b/index.html
deleted file mode 100644
index b83255b..0000000
--- a/index.html
+++ /dev/null
@@ -1,165 +0,0 @@
-
-
-
- go-scan
-
-
-
-
-
-
-
go-scan
-
-
-
- filename:
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/main.go b/main.go
index da791b8..745e4cf 100644
--- a/main.go
+++ b/main.go
@@ -1,6 +1,7 @@
package main
import (
+ "embed"
_ "embed"
"encoding/json"
"fmt"
@@ -14,8 +15,8 @@ import (
"velvettear/go-scan/util/date"
)
-//go:embed index.html
-var html []byte
+//go:embed resources
+var resources embed.FS
var configuration config.Config
@@ -26,6 +27,8 @@ func main() {
func startServer() {
serverAddress := configuration.ServerConfig.Address + ":" + configuration.ServerConfig.Port
+ http.HandleFunc("/favicon.ico", serveResources)
+ http.HandleFunc("/resources/", serveResources)
http.HandleFunc("/", handleHTTPRequests)
log.Info("starting server '" + serverAddress + "'...")
error := http.ListenAndServe(serverAddress, nil)
@@ -34,6 +37,25 @@ func startServer() {
}
}
+func serveResources(writer http.ResponseWriter, request *http.Request) {
+ var resource string
+ if strings.HasSuffix(request.URL.Path, "favicon.ico") {
+ resource = "resources/gopher.png"
+ } else {
+ resource = strings.TrimPrefix(request.URL.Path, "/")
+ }
+ bytes, error := resources.ReadFile(resource)
+ if error != nil {
+ log.Error("an error occured serving the resource '"+resource+"'", error.Error())
+ return
+ }
+ log.Debug("serving '" + resource + "'...")
+ if strings.HasSuffix(resource, "svg") {
+ writer.Header().Set("Content-Type", "image/svg+xml")
+ }
+ writer.Write(bytes)
+}
+
func handleHTTPRequests(writer http.ResponseWriter, request *http.Request) {
if strings.ToLower(request.Method) == "post" {
result := handleScan(request)
@@ -42,7 +64,14 @@ func handleHTTPRequests(writer http.ResponseWriter, request *http.Request) {
writer.Write(json)
return
}
- writer.Write(html)
+ resource := "resources/index.html"
+ bytes, error := resources.ReadFile(resource)
+ if error != nil {
+ log.Error("an error occured serving the resource '"+resource+"'", error.Error())
+ return
+ }
+ log.Debug("serving '" + resource + "'...")
+ writer.Write(bytes)
}
func handleScan(request *http.Request) *result {
diff --git a/resources/firacode.ttf b/resources/firacode.ttf
new file mode 100644
index 0000000..f75b2a2
Binary files /dev/null and b/resources/firacode.ttf differ
diff --git a/resources/gopher.png b/resources/gopher.png
new file mode 100644
index 0000000..8f29b63
Binary files /dev/null and b/resources/gopher.png differ
diff --git a/resources/heart.png b/resources/heart.png
new file mode 100644
index 0000000..9b7f140
Binary files /dev/null and b/resources/heart.png differ
diff --git a/resources/hearts-fill.svg b/resources/hearts-fill.svg
new file mode 100644
index 0000000..5abc1ab
--- /dev/null
+++ b/resources/hearts-fill.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/resources/icon.png b/resources/icon.png
new file mode 100644
index 0000000..618ee6a
Binary files /dev/null and b/resources/icon.png differ
diff --git a/resources/index.html b/resources/index.html
new file mode 100644
index 0000000..166f4c8
--- /dev/null
+++ b/resources/index.html
@@ -0,0 +1,34 @@
+
+
+
+ go-scan
+
+
+
+
+
+
+
+
go-scan
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/main.js b/resources/main.js
new file mode 100644
index 0000000..f9cfb90
--- /dev/null
+++ b/resources/main.js
@@ -0,0 +1,87 @@
+// key listener
+document.addEventListener("keypress", function onEvent(event) {
+ if (event.key !== "Enter") {
+ return;
+ }
+ startScan();
+});
+
+let scanInProgress = false;
+
+// start a scan
+function startScan() {
+ if (scanInProgress === true) {
+ return;
+ }
+ scanInProgress = true;
+ let button = document.getElementById("button");
+ let buttonDefaultColor = button.style.backgroundColor;
+ button.style.backgroundColor = "#ffee00";
+ let buttonImg = document.getElementById("button-img");
+ let result = document.getElementById("result");
+ result.style.visibility = "hidden";
+ let text = document.getElementById("text");
+ let input = document.getElementById("input");
+ input.style.opacity = "0"
+
+ // start rotate animation
+ let rotate = true;
+ let rotationDegree = 0;
+ let rotationInterval = setInterval(() => {
+ rotationDegree = rotateElement(buttonImg, rotationInterval, rotationDegree, !rotate, "Y");
+ }, 5);
+
+ // call api
+ fetch('scan', {
+ method: 'post',
+ headers: {
+ "Content-type": "application/json"
+ },
+ body: JSON.stringify({
+ filename: document.getElementById("input-filename").value
+ })
+ }).then(response => {
+ return response.json();
+ }).then(response => {
+ let buttonColor = "#008800";
+ result.style.visibility = "visible";
+ text.innerHTML = response.Message;
+ if (response.State !== "ok") {
+ text.style.color = "#ff0000";
+ buttonColor = "#880000";
+ text.innerHTML = "an error occured
" + text.innerHTML;
+ } else {
+ text.innerHTML = "scan finished
" + text.innerHTML;
+ }
+ text.style.opacity = "100";
+ button.style.backgroundColor = buttonColor;
+ rotate = false;
+ setTimeout(() => {
+ text.style.opacity = "0";
+ result.style.visibility = "hidden";
+ button.style.backgroundColor = buttonDefaultColor;
+ input.style.opacity = "100";
+ scanInProgress = false;
+ }, 5000);
+ });
+}
+
+function rotateElement(element, interval, degree, stop, direction) {
+ if (element === undefined || interval === undefined) {
+ return;
+ }
+ if (degree === undefined) {
+ degree = 0;
+ }
+ if (stop === true && degree % 360 === 0) {
+ clearInterval(interval);
+ return;
+ }
+ degree++;
+ let value = "rotate";
+ if (direction !== undefined && (direction.toLowerCase() === "x" || direction.toLowerCase() === "y")) {
+ value += direction;
+ }
+ element.style.transform = value + "(" + degree + "deg)";
+ return degree;
+}
\ No newline at end of file
diff --git a/resources/styles.css b/resources/styles.css
new file mode 100644
index 0000000..bc512a0
--- /dev/null
+++ b/resources/styles.css
@@ -0,0 +1,105 @@
+#content {
+ flex: 1 0 auto;
+}
+
+#text {
+ opacity: 0;
+ transition: opacity 0.5s;
+}
+
+#result {
+ margin-top: 5%;
+ font-weight: 600;
+ font-size: 1.5em;
+ transition: opacity 0.5s;
+}
+
+#button {
+ background-color: #6e6e6e;
+ margin: auto;
+ width: fit-content;
+ height: fit-content;
+ border: none;
+ border-radius: 100%;
+ transition: background-color 0.5s;
+}
+
+#button:hover {
+ background-color: #4e4e4e;
+ cursor: pointer;
+}
+
+#button-img {
+ min-width: 96px;
+ min-height: 96px;
+ width: 25vh;
+ height: 25vh;
+}
+
+#input {
+ margin-top: 5%;
+ transition: opacity 0.5s;
+}
+
+#input-filename {
+ padding: 8px;
+ border: 0;
+ border-radius: 8px;
+ background-color: #f1f1f1;
+ font-weight: 300;
+ font-size: 1.5rem;
+ color: #1e1e1e;
+ margin: auto;
+ font-family: 'Fira Code', monospace;
+}
+
+#footer {
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ flex-shrink: 0;
+ padding: 8px;
+ background-color: #4e4e4e;
+ font-weight: 600;
+ align-items: center;
+ transition: background-color 0.5s;
+ border-top: 1px solid #6e6e6e;
+}
+
+#footer:hover {
+ background-color: #3e3e3e;
+ cursor: pointer;
+}
+
+#heart-img {
+ height: 2rem;
+ margin-left: 8px;
+ margin-right: 8px;
+}
+
+html,
+body {
+ height: 100%;
+}
+
+body {
+ font-family: 'Fira Code', monospace !important;
+ color: #e1e1e1;
+ background-color: #1e1e1e;
+ margin: 0;
+ padding: 0;
+ text-align: center;
+ display: flex;
+ flex-direction: column;
+}
+
+h1 {
+ font-weight: 900;
+ font-size: 5rem;
+ color: #f1f1f1;
+}
+
+a {
+ text-decoration: none;
+ color: #f1f1f1;
+}
\ No newline at end of file