diff options
-rw-r--r-- | lib/DBInfoscreen.pm | 8 | ||||
-rw-r--r-- | lib/DBInfoscreen/Controller/Stationboard.pm | 35 | ||||
-rw-r--r-- | public/static/css/app.css | 736 | ||||
-rw-r--r-- | public/static/css/default.css | 367 | ||||
-rw-r--r-- | templates/layouts/app.html.ep | 258 | ||||
-rw-r--r-- | templates/layouts/legacy.html.ep (renamed from templates/layouts/default.html.ep) | 0 |
6 files changed, 1015 insertions, 389 deletions
diff --git a/lib/DBInfoscreen.pm b/lib/DBInfoscreen.pm index d83f58f..44a5520 100644 --- a/lib/DBInfoscreen.pm +++ b/lib/DBInfoscreen.pm @@ -261,7 +261,7 @@ sub startup { $r->get('/_wr/:train/:departure')->to('wagenreihung#wagenreihung'); - $self->defaults( layout => 'default' ); + $self->defaults( layout => 'app' ); $self->sessions->default_expiration( 3600 * 24 * 28 ); $r->get('/')->to('stationboard#handle_request'); @@ -270,12 +270,12 @@ sub startup { $self->config( hypnotoad => { - accepts => $ENV{DBFAKEDISPLAY_ACCEPTS} // 100, - clients => $ENV{DBFAKEDISPLAY_CLIENTS} // 10, + accepts => $ENV{DBFAKEDISPLAY_ACCEPTS} // 100, + clients => $ENV{DBFAKEDISPLAY_CLIENTS} // 10, listen => [ $ENV{DBFAKEDISPLAY_LISTEN} // 'http://*:8092' ], pid_file => $ENV{DBFAKEDISPLAY_PID_FILE} // '/tmp/db-fakedisplay.pid', - spare => $ENV{DBFAKEDISPLAY_SPARE} // 2, + spare => $ENV{DBFAKEDISPLAY_SPARE} // 2, workers => $ENV{DBFAKEDISPLAY_WORKERS} // 2, }, ); diff --git a/lib/DBInfoscreen/Controller/Stationboard.pm b/lib/DBInfoscreen/Controller/Stationboard.pm index 862ba12..e0e778d 100644 --- a/lib/DBInfoscreen/Controller/Stationboard.pm +++ b/lib/DBInfoscreen/Controller/Stationboard.pm @@ -373,22 +373,22 @@ sub handle_request { my $via = $self->param('via'); my @platforms = split( /,/, $self->param('platforms') // q{} ); - my @lines = split( /,/, $self->param('lines') // q{} ); - my $template = $self->param('mode') // 'app'; - my $hide_low_delay = $self->param('hidelowdelay') // 0; - my $hide_opts = $self->param('hide_opts') // 0; + my @lines = split( /,/, $self->param('lines') // q{} ); + my $template = $self->param('mode') // 'app'; + my $hide_low_delay = $self->param('hidelowdelay') // 0; + my $hide_opts = $self->param('hide_opts') // 0; my $show_realtime = $self->param('show_realtime') // 0; - my $show_details = $self->param('detailed') // 0; - my $backend = $self->param('backend') // 'iris'; - my $admode = $self->param('admode') // 'deparr'; - my $dark_layout = $self->param('dark') // 0; - my $apiver = $self->param('version') // 0; + my $show_details = $self->param('detailed') // 0; + my $backend = $self->param('backend') // 'iris'; + my $admode = $self->param('admode') // 'deparr'; + my $dark_layout = $self->param('dark') // 0; + my $apiver = $self->param('version') // 0; my $callback = $self->param('callback'); my $with_related = !$self->param('no_related'); my $save_defaults = $self->param('save_defaults') // 0; - my $limit = $self->param('limit') // 0; - my @train_types = split( /,/, $self->param('train_types') // q{} ); - my %opt = ( + my $limit = $self->param('limit') // 0; + my @train_types = split( /,/, $self->param('train_types') // q{} ); + my %opt = ( cache_hafas => $self->app->cache_hafas, cache_iris_main => $self->app->cache_iris_main, cache_iris_rt => $self->app->cache_iris_rt, @@ -423,6 +423,9 @@ sub handle_request { elsif ( defined $station and $station =~ s{ [.] json $ }{}x ) { $template = 'json'; } + elsif ( $template ne 'app' ) { + $self->stash( layout => 'legacy' ); + } # Historically, there were two JSON APIs: 'json' (undocumented, raw # passthrough of serialized Travel::Status::DE::IRIS::Result / @@ -452,11 +455,7 @@ sub handle_request { $self->param( $param => $self->session($param) ); } } - $self->render( - 'landingpage', - hide_opts => 0, - show_intro => 1 - ); + $self->render( 'landingpage', show_intro => 1 ); return; } @@ -554,7 +553,7 @@ sub handle_request { for my $result (@results) { my $platform = ( split( qr{ }, $result->platform // '' ) )[0]; - my $delay = $result->delay; + my $delay = $result->delay; if ( $backend eq 'iris' and $admode eq 'arr' and not $result->arrival ) { next; diff --git a/public/static/css/app.css b/public/static/css/app.css new file mode 100644 index 0000000..9cabc12 --- /dev/null +++ b/public/static/css/app.css @@ -0,0 +1,736 @@ +body { + margin: 0; +} + +html { + font-family: Sans-Serif; +} + +a { + color: #000099; + text-decoration: none; +} + +p, +div.about, +div.input-field, +div.notes { + max-width: 94%; + margin-left: auto; + margin-right: auto; +} + +p { + text-align: justify; +} + +div.content { + width: 100%; + margin: 0; +} + +div.app { + border-width:1px 2px; + width:100%; + margin-bottom: 5em; +} + +div.app > ul { + position:relative; + width:100%; + + list-style-type:none; + margin:0; + padding:0; +} + +div.app > ul > li { + min-height:7em; + display:block; + width:100%; + position:relative; + cursor: pointer; +} + +div.appdark > ul > li { + border-bottom: 1px solid #999999; + background-color: #000000; +} + +div.applight > ul > li { + border-bottom: 1px solid #999999; + background-color: #ffffff; +} + +div.app li .line { + font-size: 2.7em; + position:absolute; + bottom:5px; + left:2px; + max-width: 6em; + max-height: 3ex; + overflow: hidden; +} + +div.app li .line .trainno { + font-weight: normal; +} + +div.app li .line .trainno_sub { + font-weight: normal; + font-size: 0.6em; + text-align: center; + margin-top: -0.2em; +} + +div.app li .sbahn .trainno_sub { + font-weight: normal; + font-size: 0.5em; + text-align: center; + margin-top: -0.25em; +} + +div.app li .lineinfo { + color:#000000; + font-size: 2em; + position:absolute; + top:0px; + left:2px; +} + +div.app .replacement { + color: #006600; +} + +div.app .replaced { + color: #660000; +} + +div.app .sbahn { + font-weight:bold; + border-radius: 30px; + padding:3px 6px 2px 6px; +} + +div.applight .sbahn { + background-color:#95d79f; +} + +div.appdark .sbahn { + background-color:#115511; +} + +div.app .bahn, +div.app .fern, +div.app .ext { + font-weight:bold; + border-radius: 5px; + padding:3px 5px 2px 5px; +} + +div.applight .bahn { + background-color: #eeeeee; +} + +div.appdark .bahn { + background-color: #333333; +} + +div.applight .fern { + background-color: #ffdddd; +} + +div.appdark .fern { + background-color: #551111; +} + +div.applight .ext { + background-color: #ffdddd; + border: 2px solid #ff6666; +} + +div.appdark .ext { + background-color: #551111; + border: 2px solid #993333; +} + +div.app li .route { + background-color: transparent; + font-size:2.1em; + position:absolute; + top:1px; + left:7.7em; + height: 1.2em; + width: 70%; + overflow: hidden; +} + +div.applight li .route { + color:#444444; +} + +div.appdark li .route { + color:#bbbbbb; +} + +div.app li .info { + color:#ff0000; + background-color: transparent; + font-size:2.1em; + position:absolute; + top:1px; + left:7.7em; + height: 1.2em; + width: 70%; + overflow: hidden; +} + +div.app .moreinfo { + font-size:2.1em; + position:fixed; + top:64px; + left:0; + right:0; + bottom:0em; + z-index: 5; + overflow: auto; + cursor: default; +} + +div.app .moreinfo .mheader, +div.app .moreinfo .mfooter { + max-width: 50em; + margin-left: auto; + margin-right: auto; +} + +div.applight .moreinfo { + background-color: #ffffff; +} + +div.appdark .moreinfo { + background-color: #000000; +} + +div.app .collapsed-moreinfo { + display: none; +} + +div.app .expanded-moreinfo { + display: block; +} + +div.app .moreinfo .mheader { + text-align: center; + font-size: 120%; + padding-top: 0.5em; + padding-bottom: 0.5em; + padding-left: 1em; + padding-right: 1em; + border-bottom: 0.1em dashed #cccccc; +} + +div.app .moreinfo .mfooter { + padding-top: 1em; + padding-left: 1em; + padding-right: 1em; +} + +div.app .moreinfo .reason, +div.app .moreinfo .minfo { + color: #ff0000; +} + +div.app .moreinfo .verbose { + margin-bottom: 0.6em; +} + +div.app .moreinfo .timeinfo { + margin-bottom: 0.6em; +} + +div.applight .moreinfo .mroute .important-stop { + color: #000000; +} + +div.appdark .moreinfo .mroute .important-stop { + color: #ffffff; +} + +div.applight .moreinfo .mroute .generic-stop { + color: #555555; +} + +div.appdark .moreinfo .mroute .generic-stop { + color: #999999; +} + +div.applight .moreinfo .mroute .additional-stop { + color: #009900; +} + +div.appdark .moreinfo .mroute .additional-stop { + color: #009900; +} + +div.applight .moreinfo .mroute .cancelled-stop { + color: #cc0000; +} + +div.appdark .moreinfo .mroute .cancelled-stop { + color: #cc0000; +} + +div.app li .dest { + background-color: transparent; + font-size:4em; + position:absolute; + top:0.62em; + left:4em; + bottom:0px; + width: 70%; + overflow: hidden; +} + +div.applight li .dest { + color:#000000; +} + +div.appdark li .dest { + color:#ffffff; +} + +div.applight li.cancelled { + background-color: #ffe7d0; +} + +div.appdark li.cancelled { + background-color: #512f00; +} + +div.app li .countdown { + background-color: transparent; + font-size: 3em; + position: absolute; + right: 5px; + bottom: 2px; + padding-left: 0.2em; +} + +div.applight li .countdown { + color: #000000; +} + +div.appdark li .countdown { + color: #ffffff; +} + +div.app li .header { + color:#000000; + font-size:2em; + font-weight:bold; + padding-top:8px; + border-width-top:0; + display:block; + text-align:center; +} + +div.app li .head { + border-bottom-width:0; +} + +div.app li .countdown .delay { + font-size:1em; + color:#FF0000; + background-color: transparent; + padding-right:7px; +} + +div.app li .countdown .undelay { + font-size:1em; + color:#006600; + padding-right:7px; +} + +div.app li .countdown .delaynorm { + font-size:0.9em; + color:#BB3333; + padding-right:7px; +} + +div.app li .countdown .undelaynorm { + font-size:0.9em; + color:#338833; + padding-right:7px; +} + +div.app li .countdown .platform { + font-weight: bold; +} + +div.app li .countdown .changed-platform { + color:#ff0000; +} + +div.app li .time { + background-color: transparent; + font-size:2.3em; + position:absolute; + right:5px; + top:4px; + padding-left: 0.2em; +} + +div.applight li .time { + color:#000000; +} + +div.appdark li .time { + color:#ffffff; +} + +div.app span.delayed { + color: #ff0000; + background-color: transparent; +} + +ul.ui-autocomplete { + max-height: 20em; + overflow-x: hidden; + overflow-y: auto; +} + +div.geolocation { + text-align: center; +} + +div.candidatestatus { + text-align: center; + color: #999999; +} + +div.candidatelist a { + display: block; + text-decoration: none; + font-size: 1.4em; + padding-top: 0.3em; + text-align: center; + border-bottom: 1px solid #999999; +} + +div.candidatelist a .distance:after { + content: " km"; +} + +div.candidatelist a .distance { + font-size: 0.6em; + color: #999999; + padding-top: 0.2em; + padding-bottom: 0.3em; +} + +div.about { + margin-top: 2em; + font-family: Sans-Serif; + color: #666666; +} + +div.about a { + color: #000066; + text-decoration: none; +} + +.notice { + padding: 15px; + margin-bottom: 20px; + border: 1px solid #bce8f1; + border-radius: 4px; + color: #31708f; + background-color: #d9edf7; + margin-left: auto; + margin-right: auto; +} + +.warning { + padding: 15px; + margin-bottom: 20px; + border: 1px solid #faebcc; + border-radius: 4px; + color: #8a6d3b; + background-color: #fcf8e3; + margin-left: auto; + margin-right: auto; +} + +.error { + padding: 15px; + margin-bottom: 20px; + border: 1px solid #ebccd1; + border-radius: 4px; + color: #a94442; + background-color: #f2dede; + margin-left: auto; + margin-right: auto; +} + +.error .errcode { + font-family: Monospace; + margin-top: 2em; + font-size: 100%; + color: #aaaaaa; +} + +.container { + max-width: 60em; + margin-left: auto; + margin-right: auto; +} + +pre { + margin-bottom: 2em; +} + +span.optional, +span.notes { + color: #666666; +} + +.moresettings-header { + cursor: pointer; +} + +.moresettings-header-collapsed:before { + content: "▹ " +} + +.moresettings-header-expanded:before { + content: "▿ " +} + +.moresettings-collapsed { + display: none; +} + +.moresettings-expanded { + display: block; +} + +.developers-header { + cursor: pointer; +} + +.developers-header-collapsed:before { + content: "▹ " +} + +.developers-header-expanded:before { + content: "▿ " +} + +.developers-collapsed { + display: none; +} + +.developers-expanded { + display: block; +} + +div.break { + height: 1em; +} + +div.field { + margin-top: 0.3em; + margin-bottom: 0.6em; +} + +input, select, .button { + display: inline-block; + width: 60em; + max-width: 100%; + min-height: 1.8em; + border-radius: 4px; + color: #000; + background-color: #fff; + border: 1px solid #ccc; + box-shadow: inset 0 1px 1px rgba(0,0,0,.075); + font-size: 90%; + text-align: center; + vertical-align: middle; +} + +input[type="text"] { + width: 59em; + padding-left: 0.5em; + padding-right: 0.5em; + text-align: left; + box-sizing: border-box; +} + +select { + min-height: 2em; +} + +input[type="checkbox"] { + width: 1.5em; + box-shadow: none; +} + +input[type="submit"], .button { + color: #fff; + background-color: #337ab7; + border-color: #2e6da4; + cursor: pointer; + box-shadow: none; + padding-top: 0.9ex; + padding-bottom: 0.9ex; +} + +.button { + padding-top: 1.1ex; + padding-bottom: 0; +} + +input[type="submit"]:active, +input[type="submit"]:focus, +input[type="submit"]:hover, +.button:active, +.button:focus, +.button:hover { + color: #fff; + background-color: #286090; + border-color: #204d74; +} + +input[type="submit"]:active, +.button.active { + box-shadow: inset 0 3px 5px rgba(0,0,0,.125); +} + +.button-light { + color: #333; + background-color: #fff; + border-color: #ccc; +} + +.button-light:active, +.button-light:focus, +.button-light:hover +{ + color: #333; + background-color: #e6e6e6; + border-color: #adadad; +} + +div.notes { + margin-top: 2em; +} + +div.notes ul { + margin-top: 1em; +} +div.app { + max-width: 60em; + margin-left: auto; + margin-right: auto; +} + +.navbar-fixed { + position: relative; + z-index: 997; +} + +.navbar-fixed nav { + position: fixed; +} + +nav { + box-shadow: 0 2px 2px 0 rgba(0,0,0,.14), 0 3px 1px -2px rgba(0,0,0,.12), 0 1px 5px 0 rgba(0,0,0,.2); +} + +nav { + width: 100%; +} + +nav .nav-wrapper { + position: relative; + height: 100%; +} + +nav i, nav i.material-icons { + display: block; + font-size: 24px; +} + +nav .brand-logo { + position: absolute; + display: inline-block; + font-size: 2.1rem; + padding-left: 0.5rem; +} + +nav ul { + margin: 0; + padding-left: 0; + list-style-type: none; +} + +nav ul li { + transition: background-color .3s; + float: left; + padding: 0; + list-style-type: none; +} + +nav ul a { + transition: background-color .3s; + font-size: 1rem; + color: #fff; + display: block; + padding: 0 15px; + cursor: pointer; +} + +@media only screen and (max-width: 600px) { + div.app > ul > li { + font-size: 35%; + } + div.navbar-fixed { + height: 56px; + } + .moreinfo { + top: 56px; + } + nav { + height: 56px; + line-height: 56px; + } + nav .nav-wrapper i { + height: 56px; + line-height: 56px; + } +} + +@media only screen and (min-width: 600px) { + div.app > ul > li { + font-size: 40%; + } + div.navbar-fixed { + height: 64px; + } + nav { + height: 64px; + line-height: 64px; + } + nav .nav-wrapper i { + height: 64px; + line-height: 64px; + } +} + +div.app .moreinfo { + font-size: 100%; +} + +.content { +} diff --git a/public/static/css/default.css b/public/static/css/default.css index aca2dba..f5cb255 100644 --- a/public/static/css/default.css +++ b/public/static/css/default.css @@ -29,373 +29,6 @@ div.content { margin: 0; } -div.app { - border-width:1px 2px; - width:100%; - margin-bottom: 5em; -} - -div.app > ul { - position:relative; - width:100%; - - list-style-type:none; - margin:0; - padding:0; -} - -div.app > ul > li { - min-height:7em; - display:block; - width:100%; - position:relative; - cursor: pointer; -} - -div.appdark > ul > li { - border-bottom: 1px solid #999999; - background-color: #000000; -} - -div.applight > ul > li { - border-bottom: 1px solid #999999; - background-color: #ffffff; -} - -div.app li .line { - font-size: 2.7em; - position:absolute; - bottom:5px; - left:2px; - max-width: 6em; - max-height: 3ex; - overflow: hidden; -} - -div.app li .line .trainno { - font-weight: normal; -} - -div.app li .line .trainno_sub { - font-weight: normal; - font-size: 0.6em; - text-align: center; - margin-top: -0.2em; -} - -div.app li .sbahn .trainno_sub { - font-weight: normal; - font-size: 0.5em; - text-align: center; - margin-top: -0.25em; -} - -div.app li .lineinfo { - color:#000000; - font-size: 2em; - position:absolute; - top:0px; - left:2px; -} - -div.app .replacement { - color: #006600; -} - -div.app .replaced { - color: #660000; -} - -div.app .sbahn { - font-weight:bold; - border-radius: 30px; - padding:3px 6px 2px 6px; -} - -div.applight .sbahn { - background-color:#95d79f; -} - -div.appdark .sbahn { - background-color:#115511; -} - -div.app .bahn, -div.app .fern, -div.app .ext { - font-weight:bold; - border-radius: 5px; - padding:3px 5px 2px 5px; -} - -div.applight .bahn { - background-color: #eeeeee; -} - -div.appdark .bahn { - background-color: #333333; -} - -div.applight .fern { - background-color: #ffdddd; -} - -div.appdark .fern { - background-color: #551111; -} - -div.applight .ext { - background-color: #ffdddd; - border: 2px solid #ff6666; -} - -div.appdark .ext { - background-color: #551111; - border: 2px solid #993333; -} - -div.app li .route { - background-color: transparent; - font-size:2.1em; - position:absolute; - top:1px; - left:7.7em; - height: 1.2em; - width: 70%; - overflow: hidden; -} - -div.applight li .route { - color:#444444; -} - -div.appdark li .route { - color:#bbbbbb; -} - -div.app li .info { - color:#ff0000; - background-color: transparent; - font-size:2.1em; - position:absolute; - top:1px; - left:7.7em; - height: 1.2em; - width: 70%; - overflow: hidden; -} - -div.app .moreinfo { - font-size:2.1em; - position:fixed; - top:0em; - left:0; - right:0; - bottom:0em; - z-index: 5; - overflow: auto; - cursor: default; -} - -div.app .moreinfo .mheader, -div.app .moreinfo .mfooter { - max-width: 50em; - margin-left: auto; - margin-right: auto; -} - -div.applight .moreinfo { - background-color: #ffffff; -} - -div.appdark .moreinfo { - background-color: #000000; -} - -div.app .collapsed-moreinfo { - display: none; -} - -div.app .expanded-moreinfo { - display: block; -} - -div.app .moreinfo .mheader { - text-align: center; - font-size: 120%; - padding-top: 0.5em; - padding-bottom: 0.5em; - padding-left: 1em; - padding-right: 1em; - border-bottom: 0.1em dashed #cccccc; -} - -div.app .moreinfo .mfooter { - padding-top: 1em; - padding-left: 1em; - padding-right: 1em; -} - -div.app .moreinfo .reason, -div.app .moreinfo .minfo { - color: #ff0000; -} - -div.app .moreinfo .verbose { - margin-bottom: 0.6em; -} - -div.app .moreinfo .timeinfo { - margin-bottom: 0.6em; -} - -div.applight .moreinfo .mroute .important-stop { - color: #000000; -} - -div.appdark .moreinfo .mroute .important-stop { - color: #ffffff; -} - -div.applight .moreinfo .mroute .generic-stop { - color: #555555; -} - -div.appdark .moreinfo .mroute .generic-stop { - color: #999999; -} - -div.applight .moreinfo .mroute .additional-stop { - color: #009900; -} - -div.appdark .moreinfo .mroute .additional-stop { - color: #009900; -} - -div.applight .moreinfo .mroute .cancelled-stop { - color: #cc0000; -} - -div.appdark .moreinfo .mroute .cancelled-stop { - color: #cc0000; -} - -div.app li .dest { - background-color: transparent; - font-size:4em; - position:absolute; - top:0.62em; - left:4em; - bottom:0px; - width: 70%; - overflow: hidden; -} - -div.applight li .dest { - color:#000000; -} - -div.appdark li .dest { - color:#ffffff; -} - -div.applight li.cancelled { - background-color: #ffe7d0; -} - -div.appdark li.cancelled { - background-color: #512f00; -} - -div.app li .countdown { - background-color: transparent; - font-size: 3em; - position: absolute; - right: 5px; - bottom: 2px; - padding-left: 0.2em; -} - -div.applight li .countdown { - color: #000000; -} - -div.appdark li .countdown { - color: #ffffff; -} - -div.app li .header { - color:#000000; - font-size:2em; - font-weight:bold; - padding-top:8px; - border-width-top:0; - display:block; - text-align:center; -} - -div.app li .head { - border-bottom-width:0; -} - -div.app li .countdown .delay { - font-size:1em; - color:#FF0000; - background-color: transparent; - padding-right:7px; -} - -div.app li .countdown .undelay { - font-size:1em; - color:#006600; - padding-right:7px; -} - -div.app li .countdown .delaynorm { - font-size:0.9em; - color:#BB3333; - padding-right:7px; -} - -div.app li .countdown .undelaynorm { - font-size:0.9em; - color:#338833; - padding-right:7px; -} - -div.app li .countdown .platform { - font-weight: bold; -} - -div.app li .countdown .changed-platform { - color:#ff0000; -} - -div.app li .time { - background-color: transparent; - font-size:2.3em; - position:absolute; - right:5px; - top:4px; - padding-left: 0.2em; -} - -div.applight li .time { - color:#000000; -} - -div.appdark li .time { - color:#ffffff; -} - -div.app span.delayed { - color: #ff0000; - background-color: transparent; -} - -/* ... */ - div.infoscreen { border-width:1px 2px; width:100%; diff --git a/templates/layouts/app.html.ep b/templates/layouts/app.html.ep new file mode 100644 index 0000000..6189c9c --- /dev/null +++ b/templates/layouts/app.html.ep @@ -0,0 +1,258 @@ +<!DOCTYPE html> +<html lang="de"> +<head> + <title><%= stash('title') // 'DBF' %></title> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <meta name="keywords" content="Abfahrtsmonitor, Bahnhofstafel, Abfahrten, Abfahrtstafel, ICE, IC, RE, RB, S-Bahn"> + <meta name="description" content="Inoffizieller Abfahrtsmonitor für Bahnhöfe der DB"> + <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"> +% if ($self->stash('refresh_interval')) { + <meta http-equiv="refresh" content="<%= $self->stash('refresh_interval') %>"/> +% } + + % my $av = 'v15'; # asset version + %= stylesheet "/static/${av}/css/app.css" + %= stylesheet "/static/${av}/css/material-icons.css" + %= stylesheet "/static/${av}/css/jquery-ui.min.css" + %= javascript '/static/js/jquery-3.4.1.min.js', defer => undef + %= javascript "/static/${av}/js/jquery-ui.min.js", defer => undef + %= javascript "/static/${av}/js/dbf.min.js", defer => undef + % if (stash('with_geolocation')) { + %= javascript "/static/${av}/js/geolocation.min.js", defer => undef + % } +</head> +<body> + +<div class="navbar-fixed"> + <nav style="color: #ffffff; background-color: #00838f;"> + <div class="nav-wrapper container"> + <span class="brand-logo"> + %= stash('title') || 'DBF' + </span> + <ul id="nav-mobile" style="float: right;"> + <li><a href="#stationinput"><i class="material-icons">edit</i></a></li> + <li><a href="/_auto"><i class="material-icons">my_location</i></a></li> + </ul> + </div> + </nav> +</div> + +<div class="container"> +% if (my $error = stash 'error') { +<div class="error"><strong>Backend-Fehler:</strong> +<pre> +%= $error +</pre> +</div> +% } +% elsif (stash('stationlist')) { +<div class="error"><strong>Mehrdeutige Eingabe.</strong> +Bitte eine Station aus der Liste auswählen</div> +% } +</div> + +<div class="content"> +%= content +</div> + +% if (not stash('hide_opts')) { +<div class="container"> +<div class="input-field"> + + +%= form_for _redirect => begin +<div> + <div class="field"> + <div class="desc">Bahnhof / Haltestelle</div> + <div> +% if (stash('stationlist')) { + %= select_field station => stash('stationlist') +% } +% elsif (stash('station')) { + %= text_field 'station', class => 'station', placeholder => 'Name oder DS100-Kürzel', id => 'stationinput' +% } +% else { + %= text_field 'station', class => 'station', placeholder => 'Name oder DS100-Kürzel', id => 'stationinput', autofocus => 'autofocus' +% } + </div> + </div> + <div class="field"> + %= submit_button 'Abfahrtsmonitor' + </div> + % if (not stash('show_intro')) { + <div class="break"></div> + <div class="field"> + <a class="button" href="<%= url_for('_auto')->to_abs->scheme('https') %>">Bahnhöfe im Umfeld suchen</a> + </div> + % } + <div class="break"></div> + <div class="moresettings-header moresettings-header-collapsed button button-light">Weitere Einstellungen</div> + <div class="moresettings moresettings-collapsed"> + <div class="field"> + <div class="desc"> + Frontend + </div> + <div> + %= select_field mode => [ ['App' => 'app'], ['Infoscreen' => 'infoscreen'], ['Bahnhofstafel' => 'multi'], ['Gleisanzeiger' => 'single'] ] + </div> + </div> + <div class="field"> + <div class="desc"> + Backend + </div> + <div> + %= select_field backend => [ ['IRIS' => 'iris'], ['HAFAS' => 'ris'] ] + </div> + </div> + <div class="field"> + <div class="desc"> + Nur Züge über + </div> + <div> + %= text_field 'via', placeholder => 'Bahnhof 1, Bhf2, ... (oder regulärer Ausdruck)', class => 'station' + </div> + </div> + <div class="field"> + <div class="desc"> + Gleise + </div> + <div> + %= text_field 'platforms', placeholder => '1, 2, 5, ...' + </div> + </div> + <div class="field"> + <div class="desc"> + %= check_box 'hidelowdelay' => 1, id => 'id_hidelowdelay' + <label for="id_hidelowdelay"> + Nur Verspätungen >5 Min. anzeigen + </label> + </div> + </div> + <div class="field"> + <div class="desc"> + %= check_box 'dark' => 1, id => 'id_dark' + <label for="id_dark"> + Dunkles Layout (experimentell) + </label> + </div> + </div> + <div class="field"> + <div class="desc"> + %= check_box 'hide_opts' => 1, id => 'id_hide_opts' + <label for="id_hide_opts"> + Formular verstecken (für Infoscreens) + </label> + </div> + </div> + <div class="break"></div> + <span class="optional">Nur für IRIS-Backend:</span> + <div class="field"> + <div class="desc"> + Ankunfts- oder Abfahrtszeit anzeigen? + </div> + <div> + %= select_field admode => [['Abfahrt bevorzugen' => 'deparr'], ['Nur Abfahrt' => 'dep'], ['Nur Ankunft' => 'arr']] + </div> + </div> + <div class="field"> + <div class="desc"> + %= check_box 'detailed' => 1, id => 'id_detailed' + <label for="id_detailed"> + Mehr Details (Zugnummern und Ankunftszeiten) anzeigen + </label> + </div> + </div> + <div class="field"> + <div class="desc"> + %= check_box 'show_realtime' => 1, id => 'id_show_realtime' + <label for="id_show_realtime"> + Echtzeitangaben statt Fahrplandaten anzeigen + </label> + </div> + </div> + <div class="field"> + <div class="desc"> + %= check_box 'no_related' => 1, id => 'id_no_related' + <label for="id_no_related"> + Betriebliche Bahnhofstrennungen berücksichtigen (z.B. "Hbf (Fern+Regio)" vs. "Hbf (S)") + </label> + </div> + </div> + <div class="field"> + <div class="desc"> + %= check_box 'save_defaults' => 1, id => 'id_save_defaults' + <label for="id_save_defaults"> + Ausgewählte Optionen als Default speichern + </label> + </div> + </div> + <div class="field"> + %= submit_button 'Anzeigen' + </div> + </div> <!-- moresettings --> +</div> +% end + +</div> <!-- input-field --> + +<div class="notes"> + <div class="developers-header developers-header-collapsed button button-light">API- und Entwickler-Hinweise</div> + <div class="developers developers-collapsed"> + <ul> + <li>Diese Seite kann gerne als iframe in eigene Infoscreens o.ä. eingebunden werden. + Für eine kleine Ansicht (z.B. iframe in einer normalen Website) bitte das + "App"-Frontend verwenden. Für eine große Ansicht + (z.B. als alleinstehender Infoscreen) gibt es das "Infoscreen"-Frontend.</li> + <li>Die Parameter <span style="font-family: monospace;">mode=json&version=3</span> + (alternativ auch <span style="font-family: + monospace;">https://dbf.finalrewind.org/Bahnhofsname.json?version=3</span>) + bieten ein JSON-IRIS-Interface. Die route-Elemente können zusätzlich + die Felder "isAdditional" oder "isCancelled" enthalten, der Rest sollte + selbsterklärend sein. Im Fehlerfall fehlt das "departures"-Element, + stattdessen wird ein "error"-Element mit Fehlermeldung zurückgegeben. + Bitte nur eine Anfrage pro Station und Minute + – eine höhere Auflösung haben die Backenddaten ohnehin nicht.</li> + <li>Mit <span style="font-family: monospace;">limit</span> kann die Anzahl der + angezeigten / im JSON enthaltenen Abfahrten eingeschränkt werden, z.B. + <span style="font-family: monospace;">limit=10</span> für die ersten zehn.</li> + <li>Dieser Dienst ist Open Source-Software (Links siehe unten) und kann auch + auf eigenen Servern installiert werden. Automatisierte Crawler, die mehrere + Dutzend Stationen pro Minute abfragen, bitte nur auf eigenen Instanzen + betreiben.</li> + </ul> + </div> <!-- developers --> +</div> <!-- notes --> + +<div class="notes"> +<span class="notes">Siehe auch:</span> +<ul> +<li><a href="https://reiseauskunft.bahn.de/bin/bhftafel.exe/dn">DB Abfahrtsmonitor</a> + (<a href="https://mobile.bahn.de/bin/mobil/bhftafel.exe/dox">mobil</a>)</li> +<li>Für Nahverkehr: <a href="https://vrrf.finalrewind.org/">vrr-infoscreen</a></li> +</ul> +</div> <!-- notes --> + +</div> <!-- container --> + +<div class="container"> +<div class="about"> +<a href="_about">db-infoscreen</a> +v<%= stash('version') // '???' %> +<br/> +<a href="_datenschutz" rel="nofollow">Datenschutzerklärung</a> +· +<a href="_impressum" rel="nofollow">Impressum</a><br/> +</div> <!-- about --> +</div> <!-- container --> +% } + +</body> +</html> diff --git a/templates/layouts/default.html.ep b/templates/layouts/legacy.html.ep index 46ce984..46ce984 100644 --- a/templates/layouts/default.html.ep +++ b/templates/layouts/legacy.html.ep |