summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Friesel <derf@finalrewind.org>2021-06-26 19:55:26 +0200
committerDaniel Friesel <derf@finalrewind.org>2021-06-26 19:55:26 +0200
commitd21d35ef767007257e80a795a41b6f4cc8a9fcbc (patch)
treea5dfd5a1ed6bb823c3ef2054588d057d7cabf55d
parent1cac79ba31858b496c03762a66eb86680ff3a3da (diff)
add a landing page with geolocation search
-rwxr-xr-xbin/nvm30
-rw-r--r--static/v0/js/geolocation.js67
-rw-r--r--templates/landing_page.html36
3 files changed, 133 insertions, 0 deletions
diff --git a/bin/nvm b/bin/nvm
index d75f16e..2603679 100755
--- a/bin/nvm
+++ b/bin/nvm
@@ -22,6 +22,11 @@ headers = {
"Content-Type": "text/html; charset=utf-8",
}
+ajax_headers = {
+ "Access-Control-Allow-Origin": "*",
+ "Content-Type": "application/json; charset=utf-8",
+}
+
db_rest_api = os.getenv("NVM_DB_REST_API", "https://v5.db.transport.rest")
env = Environment(loader=FileSystemLoader("templates"), autoescape=select_autoescape())
@@ -122,6 +127,29 @@ async def show_departure_board(request):
)
+async def show_landing_page(request):
+ landing_page = env.get_template("landing_page.html")
+ return web.Response(
+ body=landing_page.render(title="Noot"),
+ headers=headers,
+ )
+
+
+async def ajax_geolocation(request):
+ request_data = await request.json()
+ lat = request_data["lat"]
+ lon = request_data["lon"]
+ async with aiohttp.ClientSession() as session:
+ async with session.get(
+ f"{db_rest_api}/stops/nearby?latitude={lat}&longitude={lon}&linesOfStops=true"
+ ) as response:
+ departures = await response.json()
+ return web.Response(
+ body=json.dumps(departures),
+ headers=ajax_headers,
+ )
+
+
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="eva to efa gateway")
@@ -130,6 +158,8 @@ if __name__ == "__main__":
args = parser.parse_args()
app = web.Application()
+ app.router.add_get(args.prefix, show_landing_page)
app.router.add_get(f"{args.prefix}board/{{eva}}", show_departure_board)
+ app.router.add_post(f"{args.prefix}geolocation", ajax_geolocation)
app.router.add_static(f"{args.prefix}static", "static")
web.run_app(app, host="localhost", port=args.port)
diff --git a/static/v0/js/geolocation.js b/static/v0/js/geolocation.js
new file mode 100644
index 0000000..7efffe0
--- /dev/null
+++ b/static/v0/js/geolocation.js
@@ -0,0 +1,67 @@
+document.addEventListener("DOMContentLoaded", function() {
+ const geoLocationButton = document.getElementById('geolocationsearch');
+
+ const processResult = function(results) {
+ console.log(results);
+ const list = document.createElement("ul");
+ for (var result in results) {
+ result = results[result];
+ var listentry = document.createElement("li");
+ var link = document.createElement("a");
+ link.text = result.name
+ link.href = "/board/" + result.id;
+ listentry.appendChild(link)
+ list.appendChild(listentry)
+ }
+ geoLocationButton.replaceWith(list);
+ };
+
+ const processLocation = function(loc) {
+ fetch('/geolocation', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({
+ lon: loc.coords.longitude,
+ lat: loc.coords.latitude
+ })
+ }).then(response => response.json()).then(processResult);
+ };
+
+ const processError = function(error) {
+ if (error.code == error.PERMISSION_DENIED) {
+ showError('Standortanfrage nicht möglich.', 'Vermutlich fehlen die Rechte im Browser oder der Android Location Service ist deaktiviert.', 'geolocation.error.PERMISSION_DENIED');
+ } else if (error.code == error.POSITION_UNAVAILABLE) {
+ showError('Standort konnte nicht ermittelt werden', 'Service nicht verfügbar', 'geolocation.error.POSITION_UNAVAILABLE');
+ } else if (error.code == error.TIMEOUT) {
+ showError('Standort konnte nicht ermittelt werden', 'Timeout', 'geolocation.error.TIMEOUT');
+ } else {
+ showError('Standort konnte nicht ermittelt werden', 'unbekannter Fehler', 'unknown geolocation.error code');
+ }
+ };
+
+ const getGeoLocation = function() {
+ geoLocationButton.textContent = "Suche Haltestellen ...";
+ geoLocationButton.disabled = true;
+ navigator.geolocation.getCurrentPosition(processLocation, processError);
+ }
+
+ if (geoLocationButton) {
+ if (navigator.geolocation) {
+ if (navigator.permissions) {
+ navigator.permissions.query({ name:'geolocation' }).then(function(value) {
+ if (value.state === 'prompt') {
+ geoLocationButton.addEventListener('click', getGeoLocation);
+ } else {
+ getGeoLocation();
+ }
+ });
+ } else {
+ geoLocationButton.addEventListener('click', getGeoLocation);
+ }
+ } else {
+ geoLocationButton.css('visibility', 'hidden');
+ }
+ }
+});
diff --git a/templates/landing_page.html b/templates/landing_page.html
new file mode 100644
index 0000000..a059b55
--- /dev/null
+++ b/templates/landing_page.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html lang="de">
+<head>
+ <title>{{ title }}</title>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta name="keywords" content="Abfahrtsmonitor, Bahnhofstafel, Abfahrten, Abfahrtstafel, Nahverkehr, Haltestellen">
+ <meta name="description" content="Inoffizieller Abfahrtsmonitor für Nahverkehr">
+ <meta name="theme-color" content="#00838f">
+ <link rel="icon" type="image/png" href="/static/icons/icon-16x16.png" sizes="16x16">
+ <link rel="icon" type="image/png" href="/static/icons/icon-32x32.png" sizes="32x32">
+ <link rel="icon" type="image/png" href="/static/icons/icon-96x96.png" sizes="96x96">
+ <link rel="apple-touch-icon" href="/static/icons/icon-120x120.png">
+ <link rel="apple-touch-icon" sizes="180x180" href="/static/icons/icon-180x180.png">
+ <link rel="apple-touch-icon" sizes="152x152" href="/static/icons/icon-152x152.png">
+ <link rel="apple-touch-icon" sizes="167x167" href="/static/icons/icon-167x167.png">
+ <link href="/static/v0/css/wip.css" id="theme" rel="stylesheet">
+ <script src="/static/v0/js/geolocation.js"></script>
+</head>
+<body>
+<div class="container">
+ <div class="content">
+ <div class="geolocation">
+ <button id="geolocationsearch">Haltestellen in der Umgebung suchen</button>
+ </div>
+ <!--<form action="/to_board" method="POST">
+ <input id="name" name="name" required type="text">
+ <label for="name">Manuelle Eingabe</label>
+ <button class="btn waves-effect waves-light btn-flat" type="submit" name="action" value="departures">
+ Suchen
+ </button>
+ </form>-->
+ </div>
+</div>
+</body>
+</html>