diff options
-rwxr-xr-x | bin/nvm | 71 | ||||
-rw-r--r-- | static/v0/css/wip.css | 78 | ||||
-rw-r--r-- | templates/departure_list.html | 34 |
3 files changed, 183 insertions, 0 deletions
@@ -0,0 +1,71 @@ +#!/usr/bin/env python3 +# vim:tabstop=4 softtabstop=4 shiftwidth=4 textwidth=160 smarttab expandtab colorcolumn=160 +# +# Copyright (C) 2021 Daniel Friesel +# +# SPDX-License-Identifier: BSD-2-Clause + +import argparse + +import aiohttp +from aiohttp import web +from datetime import datetime +import dateutil.parser + +from jinja2 import Environment, FileSystemLoader, select_autoescape + +import json +import os + +headers = { + "Access-Control-Allow-Origin": "*", + "Content-Type": "text/html; 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()) + +class Departure: + def __init__(self, obj): + self.__dict__.update(obj) + if "line" in obj: + self.line = Line(self.line) + self.when = dateutil.parser.parse(self.when) + self.plannedWhen = dateutil.parser.parse(self.plannedWhen) + +class Line: + def __init__(self, obj): + self.__dict__.update(obj) + +async def show_departure_board(request): + try: + eva = int(request.match_info.get("eva")) + except ValueError: + return web.HTTPBadRequest(text="EVA must be a number at the moment") + + async with aiohttp.ClientSession() as session: + async with session.get( + f"{db_rest_api}/stops/{eva}/departures?results=60&duration=120&stopovers=true" + ) as response: + departures = await response.text() + departures = json.loads(departures) + + if type(departures) is dict and departures.get("error", False): + return web.HTTPNotFound(body=json.dumps(departures), headers=headers) + + departures = list(map(Departure, departures)) + departure_board = env.get_template("departure_list.html") + return web.Response(body=departure_board.render(title="Noot", departures=departures), headers=headers) + +if __name__ == "__main__": + + parser = argparse.ArgumentParser(description="eva to efa gateway") + parser.add_argument("--port", type=int, metavar="PORT", default=8080) + parser.add_argument("--prefix", type=str, metavar="PATH", default="/") + args = parser.parse_args() + + app = web.Application() + app.router.add_get(f"{args.prefix}board/{{eva}}", show_departure_board) + app.router.add_static(f"{args.prefix}static", "static") + web.run_app(app, host="localhost", port=args.port) diff --git a/static/v0/css/wip.css b/static/v0/css/wip.css new file mode 100644 index 0000000..e3efc2a --- /dev/null +++ b/static/v0/css/wip.css @@ -0,0 +1,78 @@ +body { + margin: 0; + color: black; + background-color: white; +} + +html { + font-family: Sans-Serif; +} + +.container { + max-width: 60em; + margin-left: auto; + margin-right: auto; +} + +ul.departures { + position:relative; + width:100%; + + border-width:1px 2px; + margin-bottom: 5em; + + list-style-type:none; + margin:0; + padding:0; +} + +ul.departures > li { + display: block; + height: 3em; + width: 100%; + position: relative; + cursor: pointer; + border-bottom: 1px solid grey; + background-color: white; +} + +ul.departures li .line { + position: absolute; + bottom: 5px; + left: 2px; + max-width: 6em; + max-height: 3ex; + overflow: hidden; + font-size: 150%; +} + +ul.departures li .dest { + position: absolute; + top: 0.5ex; + left: 4em; + bottom: 0px; + width: 70%; + overflow: hidden; + background-color: transparent; + font-size: 200%; + color: black; +} + +ul.departures li .time { + position: absolute; + right: 5px; + top: 4px; + background-color: transparent; + font-size: 100%; + padding-left: 0.2em; + color: black; +} + +@media only screen and (max-width: 600px) { + ul.departures > li { + font-size: 85%; + } +} + +@media only screen and (min-width: 600px) { +} diff --git a/templates/departure_list.html b/templates/departure_list.html new file mode 100644 index 0000000..464951b --- /dev/null +++ b/templates/departure_list.html @@ -0,0 +1,34 @@ +<!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"> +</head> +<body> +<div class="container"> + <div class="content"> + <ul class="departures"> + {% for departure in departures %} + <li onclick="location.href='https://dbf.finalrewind.org/map/{{ departure.tripId }}/0';"> + <span class="line {{ departure.line.mode }}">{{ departure.line.name }}</span> + <span class="dest" aria-label="nach {{ departure.direction }}">{{ departure.direction }}</span> + <span class="time" aria-label="um {{ departure.when.strftime('%H:%M') }}">{{ departure.when.strftime('%H:%M') }}</span> + </li> + {% endfor %} + </ul> + </div> +</div> +</body> +</html> |