travelynx/templates/_checked_in.html.ep
Birte Kristina Friesel 47f76da4f8
Multi-backend support
Squashed commit of the following:

commit 92518024ba
Author: Birte Kristina Friesel <birte.friesel@uos.de>
Date:   Fri Jul 26 18:39:46 2024 +0200

    add_or_update station: remove superfluos 'new backend id := old backend id'

commit df21c20c6e
Author: Birte Kristina Friesel <birte.friesel@uos.de>
Date:   Fri Jul 26 18:35:51 2024 +0200

    revert connection targets min_count to 3

commit be335cef07
Author: Birte Kristina Friesel <birte.friesel@uos.de>
Date:   Fri Jul 26 18:20:05 2024 +0200

    mention backend selection in API documentation

commit 9f41828fb4
Author: Birte Kristina Friesel <derf@finalrewind.org>
Date:   Thu Jul 25 20:19:23 2024 +0200

    use_history: not all backends provide route data in departure monitor

commit 09714b4d89
Author: Birte Kristina Friesel <derf@finalrewind.org>
Date:   Thu Jul 25 20:11:44 2024 +0200

    disambiguation: pass correct hafas parameter

commit 8cdf1120fc
Author: Birte Kristina Friesel <derf@finalrewind.org>
Date:   Thu Jul 25 20:11:28 2024 +0200

    _checked_in: hide Zuglauf link for non-db checkins

commit 7455653f54
Author: Birte Kristina Friesel <derf@finalrewind.org>
Date:   Thu Jul 25 20:01:47 2024 +0200

    debug output

commit b9cda07f85
Author: Birte Kristina Friesel <derf@finalrewind.org>
Date:   Thu Jul 25 19:09:07 2024 +0200

    fix remaining get_connection_targets / get_connecting_trains_p invocations

commit 2759d7258c
Author: Birte Kristina Friesel <derf@finalrewind.org>
Date:   Wed Jul 24 20:50:12 2024 +0200

    support non-DB HAFAS backends (WiP)
2024-07-26 18:55:58 +02:00

405 lines
17 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

% my $user = current_user();
<div class="autorefresh">
<div class="card">
<div class="card-content">
<i class="material-icons right sync-failed-marker grey-text" style="display: none;">sync_problem</i>
% if (not $journey->{arr_name}) {
<span class="card-title center-align">Ziel wählen</span>
% }
<span class="card-title center-align">
%= include '_format_train', journey => $journey
</span>
% if ($journey->{comment}) {
<p><%= $journey->{comment} %></p>
% }
<p>
<div class="center-align countdown"
data-journey="<%= $journey->{real_departure}->epoch %>;<%= <%= $journey->{real_arrival}->epoch %>"
data-route="<%= journey_to_ajax_route($journey) %>"
data-dest="<%= $journey->{arr_name} %>"
>
% if ($journey->{boarding_countdown} > 60) {
Einfahrt in <%= journeys->min_to_human(int($journey->{boarding_countdown} / 60)) %><br/>
% }
% elsif ($journey->{boarding_countdown} > 0) {
Fährt ein<br/>
% }
% if ($journey->{departure_countdown} > 60) {
Abfahrt in <%= journeys->min_to_human(int($journey->{departure_countdown} / 60)) %>
% }
% elsif ($journey->{departure_countdown} > 0) {
Abfahrt in weniger als einer Minute
% }
% elsif (defined $journey->{arrival_countdown}) {
% if ($journey->{arrival_countdown} > 60) {
Ankunft in <%= journeys->min_to_human(int($journey->{arrival_countdown} / 60)) %>
% }
% elsif ($journey->{arrival_countdown} > 0) {
Ankunft in weniger als einer Minute
% }
% else {
Ziel erreicht
% }
% if ($journey->{arrival_countdown} < (60 * 15) and $journey->{arr_platform}) {
% if ($journey->{arr_direction} and $journey->{arr_direction} eq 'r') {
<br/>Gleis <%= $journey->{arr_platform} %> ▶
% }
% elsif ($journey->{arr_direction} and $journey->{arr_direction} eq 'l') {
<br/>◀ Gleis <%= $journey->{arr_platform} %>
% }
% else {
<br/>auf Gleis <%= $journey->{arr_platform} %>
% }
% }
% }
% elsif ($journey->{arr_name}) {
Ankunft in mehr als zwei Stunden
% }
% if ($journey->{departure_countdown} > 0 and $journey->{dep_platform}) {
% if ($journey->{dep_direction} and $journey->{dep_direction} eq 'r') {
<br/>Gleis <%= $journey->{dep_platform} %> ▶
% }
% elsif ($journey->{dep_direction} and $journey->{dep_direction} eq 'l') {
<br/>◀ Gleis <%= $journey->{dep_platform} %>
% }
% else {
<br/>von Gleis <%= $journey->{dep_platform} %>
% }
% }
% if (my $wr = $journey->{wagonorder}) {
<br/>
% my @wagons = $wr->wagons;
% my $direction = $wr->direction == 100 ? '→' : '←';
% if ($journey->{dep_direction}) {
% $direction = $journey->{dep_direction} eq 'l' ? '◀' : '▶';
% if (($journey->{dep_direction} eq 'l' ? 0 : 100) != $wr->direction) {
% @wagons = reverse @wagons;
% }
% }
<a href="https://dbf.finalrewind.org/_wr/<%= $journey->{train_no} %>/<%= $journey->{sched_departure}->strftime('%Y%m%d%H%M') %>?e=<%= $journey->{dep_direction} // q{} %>">
%= $direction
% my $gi;
% for my $wagon (@wagons) {
% if (not ($wagon->is_locomotive or $wagon->is_powercar)) {
% if (defined $gi and $gi != $wagon->group_index) {
% }
% if ($wagon->is_closed) {
X
% }
% else {
%= $wagon->number || ($wagon->type =~ m{AB} ? '½' : $wagon->type =~ m{A} ? '1.' : $wagon->type =~ m{B} ? '2.' : $wagon->type )
% }
% }
% $gi = $wagon->group_index;
% }
%= $direction
</a>
% }
</div>
<div class="progress" style="height: 1ex;">
<div class="determinate" style="width: <%= sprintf('%.2f', 100 * ($journey->{journey_completion} // 0)); %>%;"></div>
</div>
</p>
% if ($journey->{arr_name}) {
<p>
<div style="float: left;">
<b><%= $journey->{dep_name} %></b><br/>
<b><%= $journey->{real_departure}->strftime('%H:%M') %></b>
% if ($journey->{real_departure}->epoch != $journey->{sched_departure}->epoch) {
(<%= sprintf('%+d', ($journey->{real_departure}->epoch - $journey->{sched_departure}->epoch)/60) %>)
% }
</div>
<div style="float: right; text-align: right;">
<b><a href="<%= resolve_sb_template($user->{sb_template}, name => $journey->{arr_name}, eva => $journey->{arr_eva}, tt => $journey->{train_type} // q{x}, tn => $journey->{train_no}, id => $journey->{train_id}, hafas => $journey->{is_hafas} ? $journey->{backend_name} : q{}) %>" class="unmarked"><%= $journey->{arr_name} %></a></b><br/>
% if ($journey->{real_arrival}->epoch) {
<b><%= $journey->{real_arrival}->strftime('%H:%M') %></b>
% if ($journey->{real_arrival}->epoch != $journey->{sched_arrival}->epoch) {
(<%= sprintf('%+d', ($journey->{real_arrival}->epoch - $journey->{sched_arrival}->epoch)/60) %>)
% }
% }
% else {
noch nicht bekannt
% }
</div>
<div class="center-align hide-on-small-only next-stop">
% for my $station (@{$journey->{route_after}}) {
% if ($station->[0] eq $journey->{arr_name}) {
% last;
% }
% if (($station->[2]{arr_countdown} // 0) > 0 and $station->[2]{arr}) {
<%= $station->[0] %><br/><%= $station->[2]{arr}->strftime('%H:%M') %>
% if ($station->[2]{arr_delay}) {
%= sprintf('(%+d)', $station->[2]{arr_delay} / 60);
% }
% last;
% }
% if (($station->[2]{dep_countdown} // 0) > 0 and $station->[2]{dep}) {
<%= $station->[0] %><br/>
% if ($station->[2]{arr}) {
<%= $station->[2]{arr}->strftime('%H:%M') %> →
% }
%= $station->[2]{dep}->strftime('%H:%M')
% if ($station->[2]{dep_delay}) {
%= sprintf('(%+d)', $station->[2]{dep_delay} / 60);
% }
% last;
% }
% }
</div>
<div style="clear: both;">
</div>
<div class="hide-on-med-and-up next-stop" style="margin-top: 2ex;">
% for my $station (@{$journey->{route_after}}) {
% if ($station->[0] eq $journey->{arr_name}) {
% last;
% }
% if (($station->[2]{arr_countdown} // 0) > 0 and $station->[2]{arr}) {
<%= $station->[0] %><br/><%= $station->[2]{arr}->strftime('%H:%M') %>
% if ($station->[2]{arr_delay}) {
%= sprintf('(%+d)', $station->[2]{arr_delay} / 60);
% }
% last;
% }
% if (($station->[2]{dep_countdown} // 0) > 0 and $station->[2]{arr} and $station->[2]{dep}) {
<%= $station->[0] %><br/>
<%= $station->[2]{arr}->strftime('%H:%M') %> →
<%= $station->[2]{dep}->strftime('%H:%M') %>
% if ($station->[2]{dep_delay}) {
%= sprintf('(%+d)', $station->[2]{dep_delay} / 60);
% }
% last;
% }
% }
</div>
</p>
% }
% if ($journey->{extra_data}{cancelled_destination}) {
<p style="margin-bottom: 2ex;">
Der Halt an der Zielstation <b><%=
$journey->{extra_data}{cancelled_destination} %></b> entfällt.
Die zugehörige Fahrt wurde bereits als ausgefallen eingetragen.
Bitte wähle ein neues Reiseziel.
</p>
% }
% if (@{$journey->{messages} // []} or @{$journey->{extra_data}{qos_msg} // []} or not $journey->{extra_data}{rt}) {
<p style="margin-bottom: 2ex;">
<ul>
% if (not $journey->{extra_data}{rt}) {
<li><i class="material-icons tiny">gps_off</i> Keine Echtzeitdaten vorhanden
% }
% for my $message (reverse @{$journey->{messages} // []}) {
% if ($journey->{sched_departure}->epoch - $message->[0]->epoch < 1800) {
<li> <i class="material-icons tiny">warning</i> <%= $message->[0]->strftime('%H:%M') %>: <%= $message->[1] %></li>
% }
% }
% if ($journey->{departure_countdown} > 0) {
% for my $message (@{$journey->{extra_data}{qos_msg} // []}) {
<li> <i class="material-icons tiny">info</i> <%= $message->[0]->strftime('%H:%M') %>: <%= $message->[1] %></li>
% }
% }
</ul>
</p>
% }
% if (@{stash('connections_iris') // [] } or @{stash('connections_hafas') // []}) {
<span class="card-title" style="margin-top: 2ex;">Verbindungen</span>
% if ($journey->{arrival_countdown} < 0) {
<p>Fahrt auswählen zum Einchecken mit Zielwahl.</p>
% }
% if (@{stash('connections_iris') // [] }) {
%= include '_connections', connections => stash('connections_iris'), checkin_from => $journey->{arrival_countdown} < 0 ? $journey->{arr_eva} : undef;
% }
% if (@{stash('connections_hafas') // [] }) {
%= include '_connections_hafas', connections => stash('connections_hafas'), checkin_from => $journey->{arrival_countdown} < 0 ? $journey->{arr_eva} : undef;
% }
% }
% if (defined $journey->{arrival_countdown} and $journey->{arrival_countdown} <= 0) {
<p style="margin-top: 2ex;">
Der automatische Checkout erfolgt wegen teilweise langsamer
Echtzeitdatenupdates erst etwa zehn Minuten nach der Ankunft.
</p>
% }
% elsif (not $journey->{arr_name}) {
<p>
% for my $station (@{$journey->{route_after}}) {
<a class="tablerow action-checkout" data-station="<%= $station->[1] // $station->[0] %>">
<span><%= $station->[0] %></span>
<span>
% if ($station->[2]{load}{SECOND}) {
% my ($first, $second) = load_icon($station->[2]{load});
<i class="material-icons tiny" aria-hidden="true"><%= $first %></i> <i class="material-icons tiny" aria-hidden="true"><%= $second %></i>
% }
% if ($station->[2]{isCancelled}) {
entfällt
% }
% elsif ($station->[2]{rt_arr} or $station->[2]{sched_arr}) {
%= ($station->[2]{rt_arr} || $station->[2]{sched_arr})->strftime('%H:%M')
% }
% elsif ($station->[2]{rt_dep} or $station->[2]{sched_dep}) {
(<%= ($station->[2]{rt_dep} || $station->[2]{sched_dep})->strftime('%H:%M') %>)
% }
% elsif ($station->[2]{isAdditional}) {
Zusatzhalt
% }
</span>
</a>
% }
</p>
% }
</div>
<div class="card-action">
% if ($journey->{arr_name}) {
<a href="/journey/comment">
<i class="material-icons">comment</i>
</a>
<a style="margin-right: 0;" href="/journey/visibility">
<i class="material-icons"><%= visibility_icon($journey_visibility) %></i>
</a>
% }
% else {
<a class="action-undo blue-text" data-id="in_transit" data-checkints="<%= $journey->{timestamp}->epoch %>" style="margin-right: 0;">
<i class="material-icons left" aria-hidden="true">undo</i> Rückgängig
</a>
% }
% if (defined $journey->{arrival_countdown} and $journey->{arrival_countdown} <= 0) {
<a
class="action-checkout right"
style="margin-right: 0;"
data-station="<%= $journey->{arr_name}%>">
<i class="material-icons left">done</i>
Auschecken
</a>
% }
% elsif ($journey->{arr_name}) {
% my $attrib = 'in';
% if ($journey->{train_type} =~ m{ ^ (?: S | RB ) $ }x) {
% $attrib = 'in der';
% }
<a class="action-share blue-text right"
style="margin-right: 0;"
% my $arr_text = q{};
% if ($journey->{real_arrival}->epoch and $journey_visibility eq 'private') {
% $arr_text = $journey->{real_arrival}->strftime(' Ankunft gegen %H:%M Uhr');
% }
% if ($user->{comments_visible} and $journey->{comment}) {
data-text="<%= $journey->{comment} %> (@ <%= $journey->{train_type} %> <%= $journey->{train_no} %> → <%= $journey->{arr_name} %>) #travelynx"
% }
% else {
data-text="Ich bin gerade <%= $attrib %> <%= $journey->{train_type} %> <%= $journey->{train_no} %> nach <%= $journey->{arr_name} . $arr_text %> #travelynx"
% }
% if ($journey_visibility eq 'public') {
data-url="<%= url_for('/status')->to_abs->scheme('https') %>/<%= $user->{name} %>/<%= $journey->{sched_departure}->epoch %>"
% }
% elsif ($journey_visibility eq 'travelynx' or $journey_visibility eq 'followers' or $journey_visibility eq 'unlisted') {
data-url="<%= url_for('/status')->to_abs->scheme('https') %>/<%= $user->{name} %>/<%= $journey->{sched_departure}->epoch %>?token=<%= $journey->{dep_eva} %>-<%= $journey->{timestamp}->epoch % 337 %>"
% }
>
<i class="material-icons left" aria-hidden="true">share</i> Teilen
</a>
% }
% else {
<a class="right" href="/journey/visibility">
<i class="material-icons left"><%= visibility_icon($journey_visibility) %></i> Sichtbarkeit
</a>
% }
</div>
</div>
% if (@{stash('timeline') // []}) {
%= include '_timeline_link', timeline => stash('timeline'), from_checkin => 1
% }
% if ($journey->{arr_name}) {
<div class="card" style="margin-top: <%= scalar @{stash('timeline') // []} ? '1.5rem' : '3em' %>;">
<div class="card-content">
<span class="card-title">Details</span>
% if (@{$journey->{extra_data}{him_msg} // []}) {
<p style="margin-bottom: 2ex;">
<ul>
% for my $message (@{$journey->{extra_data}{him_msg} // []}) {
<li> <i class="material-icons tiny">info</i> <%= $message->{header} %> <%= $message->{lead} %></li>
% }
</ul>
</p>
% }
% if ($journey->{traewelling}{errored} and $journey->{traewelling_log_latest}) {
<p style="margin-bottom: 2ex;">
<ul>
<li> <i class="material-icons tiny">warning</i> Träwelling: <%= $journey->{traewelling_log_latest} %></li>
</ul>
</p>
% }
% if ($journey->{traewelling_url}) {
<p style="margin-bottom: 2ex;">
<ul>
<li> <i class="material-icons tiny">sync</i> Träwelling: <a href="<%= $journey->{traewelling_url} %>"><%= $journey->{traewelling_log_latest} %></a></li>
</ul>
</p>
% }
</div>
<div class="card-action">
% my $url = 'https://bahn.expert/details/';
% if ($journey->{train_id} =~ m{[|]}) {
% $url = $url . '/' . $journey->{sched_departure}->epoch . '000?jid=' . $journey->{train_id};
% }
% else {
% $url = $url . $journey->{train_type} . ' ' . $journey->{train_no} . '/' . $journey->{sched_departure}->epoch . '000?station=' . $journey->{dep_eva};
% }
% if ($journey->{backend_id} <= 1) {
<a style="margin-right: 0;" href="<%= $url %>"><i class="material-icons left" aria-hidden="true">timeline</i> Zuglauf</a>
% }
% else {
&nbsp;
% }
% if ($journey->{extra_data}{trip_id}) {
<a class="right" style="margin-right: 0;" href="https://dbf.finalrewind.org/map/<%= $journey->{extra_data}{trip_id} =~ s{#}{%23}gr %>/<%= $journey->{train_line} || 0 %>?hafas=<%= $journey->{backend_name} // 'DB' %>&amp;from=<%= $journey->{dep_name} %>&amp;to=<%= $journey->{arr_name} %>&amp;dark=<%= (session('theme') and session('theme') eq 'dark') ? 1 : 0 %>"><i class="material-icons left" aria-hidden="true">map</i> Karte</a>
% }
</div>
</div>
<div class="card" style="margin-top: 3em;">
<div class="card-content">
<i class="material-icons small right sync-failed-marker grey-text" style="display: none;">sync_problem</i>
<span class="card-title">Ziel ändern?</span>
<div class="targetlist">
% for my $station (@{$journey->{route_after}}) {
% my $is_dest = ($journey->{arr_name} and $station->[0] eq $journey->{arr_name});
<a class="action-checkout tablerow" style="<%= $is_dest? 'font-weight: bold;' : '' %>" data-station="<%= $station->[1] // $station->[0] %>">
<span><%= $station->[0] %></span>
<span>
% if ($station->[2]{load}{SECOND}) {
% my ($first, $second) = load_icon($station->[2]{load});
<i class="material-icons tiny" aria-hidden="true"><%= $first %></i> <i class="material-icons tiny" aria-hidden="true"><%= $second %></i>
% }
% if ($station->[2]{isCancelled}) {
entfällt
% }
% elsif ($station->[2]{rt_arr} or $station->[2]{sched_arr}) {
%= ($station->[2]{rt_arr} || $station->[2]{sched_arr})->strftime('%H:%M')
% }
% elsif ($station->[2]{rt_dep} or $station->[2]{sched_dep}) {
(<%= ($station->[2]{rt_dep} || $station->[2]{sched_dep})->strftime('%H:%M') %>)
% }
% elsif ($station->[2]{isAdditional}) {
Zusatzhalt
% }
</span>
</a>
<a class="nonflex" href="<%= resolve_sb_template($user->{sb_template}, name => $station->[0], eva => $station->[1], tt => $journey->{train_type} // q{x}, tn => $journey->{train_no}, id => $journey->{train_id}, hafas => $journey->{is_hafas} ? $journey->{backend_name} : q{}) %>"><i class="material-icons tiny"><%= $journey->{is_hafas} ? 'directions' : 'train' %></i></a>
% }
</div>
</div>
<div class="card-action">
<a class="action-undo blue-text" data-id="in_transit" data-checkints="<%= $journey->{timestamp}->epoch %>" style="margin-right: 0;">
<i class="material-icons left" aria-hidden="true">undo</i> Checkin Rückgängig
</a>
</div>
</div>
<p>
Falls das Backend ausgefallen ist oder die Fahrt aus anderen
Gründen verloren ging:
</p>
<p class="center-align">
<a class="action-checkout waves-light btn"
data-force="1" data-station="<%= $journey->{arr_name}
%>">Ohne Echtzeitdaten auschecken</a>
</p>
% }
</div>