Web: Add initial version of the Website
This commit is contained in:
parent
9730d63e58
commit
314776ac2c
|
@ -13,6 +13,7 @@ func Init() {
|
||||||
r := gin.Default()
|
r := gin.Default()
|
||||||
r.Use(cors.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.Static("/static", path.Join(config.C.Web.WebDir, "static"))
|
||||||
|
|
||||||
r.GET("/betriebsstellen/", getBetriebsstellen)
|
r.GET("/betriebsstellen/", getBetriebsstellen)
|
||||||
|
|
76
web/index.html
Normal file
76
web/index.html
Normal 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
58
web/static/db640.css
Normal 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
32
web/static/db640.js
Normal 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));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
32
web/static/img/loading.svg
Normal file
32
web/static/img/loading.svg
Normal 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 |
7
web/static/img/search.svg
Normal file
7
web/static/img/search.svg
Normal 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 |
|
@ -1,4 +0,0 @@
|
||||||
<html>
|
|
||||||
<head><title>Hello World</title></head>
|
|
||||||
<body>Hello world</body>
|
|
||||||
</html>
|
|
11965
web/static/vue.js
Normal file
11965
web/static/vue.js
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue