Web: Add initial version of the Website

This commit is contained in:
Marvin Scholz 2020-04-11 05:29:03 +02:00
parent 9730d63e58
commit 314776ac2c
8 changed files with 12171 additions and 4 deletions

View file

@ -13,6 +13,7 @@ func Init() {
r := gin.Default()
r.Use(cors.Default())
r.StaticFile("/", path.Join(config.C.Web.WebDir, "index.html"))
r.Static("/static", path.Join(config.C.Web.WebDir, "static"))
r.GET("/betriebsstellen/", getBetriebsstellen)

76
web/index.html Normal file
View file

@ -0,0 +1,76 @@
<!DOCTYPE html>
<html>
<head>
<title>DB640 Betriebsstellen</title>
<script src="/static/vue.js"></script>
<script src="/static/db640.js"></script>
<link rel="stylesheet" type="text/css" href="/static/db640.css">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="App zur Abfrage von DB640 Betriebsstellencodes">
<meta name="theme-color" content="#C1121C">
</head>
<body>
<div id="app">
<h1>DB640 Betriebsstellen</h1>
<form @submit.prevent="handleSubmit">
<label>DB640 Code</label>
<div class="field-button-group">
<input @search="handleSearch" autofocus type="search" v-model="infraCode" spellcheck="false" results="5" placeholder="Wbf" />
<button v-show="!loadingState" type="submit"><img src="/static/img/search.svg" alt="Search"></button>
<img v-show="loadingState" alt="Loading..." class="loading-spinner" src="/static/img/loading.svg" />
</div>
</form>
<p v-show="infraName">{{ infraName }}</p>
<div v-if="error" class="error-box">
<h3>Oh nein!</h3>
<p>
Ein Fehler bei der Abfrage ist aufgetreten:<br />
{{ error }}
</p>
</div>
</div>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
infraCode: null,
infraName: null,
loadingState: false,
error: null
},
methods: {
handleSubmit() {
let timer = setTimeout(() => {
app.loadingState = true;
}, 250);
RailwayInfra.lookup(app.infraCode)
.then(obj => {
app.infraName = obj.name;
})
.catch(err => {
if (err instanceof RailwayInfraLookupError) {
app.infraName = null;
} else {
console.error(err);
app.error = err.message;
}
})
.finally(() => {
clearTimeout(timer);
app.loadingState = false;
});
},
handleSearch(e) {
app.infraCode = e.target.value;
}
}
})
</script>
</body>
</html>

58
web/static/db640.css Normal file
View file

@ -0,0 +1,58 @@
body {
padding: 0;
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
}
#app {
max-width: 960px;
margin: 0 auto;
padding: 0 2%;
}
div.field-button-group {
height: 48px;
display: flex;
}
div.field-button-group input[type="search"] {
-moz-appearance: none;
-webkit-appearance: none;
outline: none;
border: 2px solid #333;
border-radius: 5px;
padding: 5px;
font-size: 200%;
min-width: 0;
flex: 1;
}
input[type="search"]::-webkit-search-results-button {
padding-right: 5px;
}
div.field-button-group input[type="search"]:focus {
border-color: #C1121C;
}
div.field-button-group button {
border: 2px solid #333;
border-radius: 5px;
padding: 10px;
width: 48px;
flex-shrink: 0;
background: #C1121C;
}
div.field-button-group img.loading-spinner {
border: 2px solid #333;
border-radius: 5px;
margin: 2px 0;
padding: 5px 0;
width: 44px;
background: #C1121C;
}

32
web/static/db640.js Normal file
View file

@ -0,0 +1,32 @@
// FIXME: This should be an absolute URL!
const DB640_API_BASE_URL = '/betriebsstellen/';
class RailwayInfraLookupError extends Error {}
class RailwayInfra {
constructor(payload) {
this.id = payload.ID;
this.code = payload.Code;
this.name = payload.Name;
}
static lookup(code) {
// FIXME: Use URL(code, DB640_API_BASE_URL) here!
let url = DB640_API_BASE_URL + encodeURI(code);
let options = {
method: 'GET',
headers: { 'Accept': 'application/json' }
};
return fetch(url, options)
.then(res => {
if (res.ok)
return res.json();
if (res.status == 404)
throw new RailwayInfraLookupError(res.statusText);
})
.then(payload => {
return Promise.resolve(new RailwayInfra(payload));
});
}
}

View file

@ -0,0 +1,32 @@
<!-- By Sam Herbert (@sherb), for everyone. More @ http://goo.gl/7AJzbL -->
<svg width="38" height="38" viewBox="0 0 38 38" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient x1="8.042%" y1="0%" x2="65.682%" y2="23.865%" id="a">
<stop stop-color="#fff" stop-opacity="0" offset="0%"/>
<stop stop-color="#fff" stop-opacity=".631" offset="63.146%"/>
<stop stop-color="#fff" offset="100%"/>
</linearGradient>
</defs>
<g fill="none" fill-rule="evenodd">
<g transform="translate(1 1)">
<path d="M36 18c0-9.94-8.06-18-18-18" id="Oval-2" stroke="url(#a)" stroke-width="2">
<animateTransform
attributeName="transform"
type="rotate"
from="0 18 18"
to="360 18 18"
dur="0.9s"
repeatCount="indefinite" />
</path>
<circle fill="#fff" cx="36" cy="18" r="1">
<animateTransform
attributeName="transform"
type="rotate"
from="0 18 18"
to="360 18 18"
dur="0.9s"
repeatCount="indefinite" />
</circle>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 200 200" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1.20031,0,0,1.20031,-12.5875,-20.0314)">
<path d="M96.501,113.159C76.935,127.667 49.141,126.053 31.403,108.316C11.89,88.803 11.89,57.118 31.403,37.605C50.917,18.092 82.601,18.092 102.114,37.605C119.852,55.343 121.466,83.137 106.958,102.703L170.828,166.573L160.372,177.03L96.501,113.159ZM40.865,47.067C55.156,32.776 78.361,32.776 92.652,47.067C106.943,61.358 106.943,84.563 92.652,98.854C78.361,113.145 55.156,113.145 40.865,98.854C26.574,84.563 26.574,61.358 40.865,47.067Z" style="fill:rgb(235,235,235);"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1,002 B

View file

@ -1,4 +0,0 @@
<html>
<head><title>Hello World</title></head>
<body>Hello world</body>
</html>

11965
web/static/vue.js Normal file

File diff suppressed because it is too large Load diff