restructured project, fixed some errors and fixed ui stuff

This commit is contained in:
Daniel Sommer 2022-06-28 15:11:46 +02:00
parent efcb1aeda3
commit 670465388e
10 changed files with 259 additions and 168 deletions

View file

@ -1,165 +0,0 @@
<html>
<head>
<title>go-scan</title>
<style>
#content {
position: absolute;
top: 33%;
left: 50%;
margin-right: -50%;
transform: translate(-50%, -50%);
height: 50%;
width: 50%;
}
#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;
}
#button-img {
min-width: 96px;
min-height: 96px;
width: 25vh;
height: 25vh;
}
#input {
margin-top: 5%;
transition: opacity 0.5s;
}
#input-label {
font-weight: 600;
font-size: 1.5rem;
margin-right: 5%;
}
body {
color: #e1e1e1;
background-color: #1e1e1e;
margin: 0;
padding: 0;
text-align: center;
}
h1 {
font-weight: 900;
font-size: 5rem;
}
</style>
</head>
<body>
<div id="content">
<div id="heading">
<h1>go-scan</h1>
</div>
<div id="button" onclick="startScan()">
<img id="button-img" src="https://cdn2.iconfinder.com/data/icons/usability-test/100/jan_yulck-26-512.png">
</div>
<div id="input">
<span id="input-label">filename:</span>
<input id="input-filename" type="text">
</div>
<div id="result">
<span id="text"></span>
</div>
</div>
</body>
<script>
function startScan() {
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 = "scan finished<br>" + response.Message;
if (response.State !== "ok") {
text.style.color = "#ff0000";
buttonColor = "#880000";
text.innerHTML = "an error occured<br>" + 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";
}, 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;
}
</script>
</html>

35
main.go
View file

@ -1,6 +1,7 @@
package main package main
import ( import (
"embed"
_ "embed" _ "embed"
"encoding/json" "encoding/json"
"fmt" "fmt"
@ -14,8 +15,8 @@ import (
"velvettear/go-scan/util/date" "velvettear/go-scan/util/date"
) )
//go:embed index.html //go:embed resources
var html []byte var resources embed.FS
var configuration config.Config var configuration config.Config
@ -26,6 +27,8 @@ func main() {
func startServer() { func startServer() {
serverAddress := configuration.ServerConfig.Address + ":" + configuration.ServerConfig.Port serverAddress := configuration.ServerConfig.Address + ":" + configuration.ServerConfig.Port
http.HandleFunc("/favicon.ico", serveResources)
http.HandleFunc("/resources/", serveResources)
http.HandleFunc("/", handleHTTPRequests) http.HandleFunc("/", handleHTTPRequests)
log.Info("starting server '" + serverAddress + "'...") log.Info("starting server '" + serverAddress + "'...")
error := http.ListenAndServe(serverAddress, nil) 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) { func handleHTTPRequests(writer http.ResponseWriter, request *http.Request) {
if strings.ToLower(request.Method) == "post" { if strings.ToLower(request.Method) == "post" {
result := handleScan(request) result := handleScan(request)
@ -42,7 +64,14 @@ func handleHTTPRequests(writer http.ResponseWriter, request *http.Request) {
writer.Write(json) writer.Write(json)
return 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 { func handleScan(request *http.Request) *result {

BIN
resources/firacode.ttf Normal file

Binary file not shown.

BIN
resources/gopher.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

BIN
resources/heart.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 713 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0H24V24H0z"/><path d="M17.363 11.045c1.404-1.393 3.68-1.393 5.084 0 1.404 1.394 1.404 3.654 0 5.047L17 21.5l-5.447-5.408c-1.404-1.393-1.404-3.653 0-5.047 1.404-1.393 3.68-1.393 5.084 0l.363.36.363-.36zm1.88-6.288c.94.943 1.503 2.118 1.689 3.338-1.333-.248-2.739-.01-3.932.713-2.15-1.303-4.994-1.03-6.856.818-2.131 2.115-2.19 5.515-.178 7.701l.178.185 2.421 2.404L11 21.485 2.52 12.993C.417 10.637.496 7.019 2.757 4.757c2.265-2.264 5.888-2.34 8.244-.228 2.349-2.109 5.979-2.039 8.242.228z"/></svg>

After

Width:  |  Height:  |  Size: 603 B

BIN
resources/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

34
resources/index.html Normal file
View file

@ -0,0 +1,34 @@
<html>
<head>
<title>go-scan</title>
<link href="/resources/firacode.ttf" rel="stylesheet">
<link href="/resources/styles.css" rel="stylesheet">
</head>
<body>
<div id="content">
<div id="heading">
<h1>go-scan</h1>
</div>
<div id="button" onclick="startScan()">
<img id="button-img" src="/resources/icon.png">
</div>
<div id="input">
<input id="input-filename" type="text" placeholder="filename...">
</div>
<div id="result">
<span id="text"></span>
</div>
</div>
<a href="https://velvettear.de" target="_blank">
<div id="footer">
<span>made with</span>
<img id="heart-img" src="/resources/hearts-fill.svg">
<span>by velvettear</span>
</div>
</a>
<script src="/resources/main.js"></script>
</body>
</html>

87
resources/main.js Normal file
View file

@ -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<br>" + text.innerHTML;
} else {
text.innerHTML = "scan finished<br>" + 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;
}

105
resources/styles.css Normal file
View file

@ -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;
}