mirror of
https://github.com/derf/travelynx
synced 2024-11-10 06:54:17 +00:00
Primitive auto-refresh of current journey status
Todo: Redirect user to destination station upon arrival
This commit is contained in:
parent
ffaa0c44a7
commit
6c1cae86f4
11 changed files with 160 additions and 101 deletions
|
@ -1505,6 +1505,7 @@ sub startup {
|
|||
);
|
||||
|
||||
$authed_r->get('/account')->to('account#account');
|
||||
$authed_r->get('/ajax/status_card.html')->to('traveling#status_card');
|
||||
$authed_r->get('/cancelled')->to('traveling#cancelled');
|
||||
$authed_r->get('/change_password')->to('account#password_form');
|
||||
$authed_r->get('/export.json')->to('account#json_export');
|
||||
|
|
|
@ -19,6 +19,20 @@ sub homepage {
|
|||
}
|
||||
}
|
||||
|
||||
sub status_card {
|
||||
my ($self) = @_;
|
||||
my $status = $self->get_user_status;
|
||||
|
||||
delete $self->stash->{layout};
|
||||
|
||||
if ( $status->{checked_in} ) {
|
||||
$self->render( '_checked_in', status => $status );
|
||||
}
|
||||
else {
|
||||
$self->render( '_checked_out', status => $status );
|
||||
}
|
||||
}
|
||||
|
||||
sub geolocation {
|
||||
my ($self) = @_;
|
||||
|
||||
|
|
|
@ -17,7 +17,16 @@ function tvly_run(link, req, err_callback) {
|
|||
}
|
||||
});
|
||||
}
|
||||
$(document).ready(function() {
|
||||
function tvly_update() {
|
||||
$.get('/ajax/status_card.html', function(data) {
|
||||
$('.statuscol').html(data);
|
||||
tvly_reg_handlers();
|
||||
setTimeout(tvly_update, 15000);
|
||||
}).fail(function() {
|
||||
setTimeout(tvly_update, 15000);
|
||||
});
|
||||
}
|
||||
function tvly_reg_handlers() {
|
||||
$('.action-checkin').click(function() {
|
||||
var link = $(this);
|
||||
var req = {
|
||||
|
@ -78,4 +87,10 @@ $(document).ready(function() {
|
|||
tvly_run(link, req);
|
||||
}
|
||||
});
|
||||
}
|
||||
$(document).ready(function() {
|
||||
tvly_reg_handlers();
|
||||
if ($('.statuscol .autorefresh').length) {
|
||||
setTimeout(tvly_update, 15000);
|
||||
}
|
||||
});
|
||||
|
|
2
public/static/js/travelynx-actions.min.js
vendored
2
public/static/js/travelynx-actions.min.js
vendored
|
@ -1 +1 @@
|
|||
function tvly_run(t,n,a){var c='<i class="material-icons">error</i>',i=$('<div class="progress"><div class="indeterminate"></div></div>');t.hide(),t.after(i),$.post("/action",n,function(n){n.success?$(location).attr("href",n.redirect_to):(M.toast({html:c+" "+n.error}),i.remove(),a&&a(),t.append(" "+c),t.show())})}$(document).ready(function(){$(".action-checkin").click(function(){var t=$(this);tvly_run(t,{action:"checkin",station:t.data("station"),train:t.data("train")})}),$(".action-checkout").click(function(){var t=$(this),n={action:"checkout",station:t.data("station"),force:t.data("force")};tvly_run(t,n,function(){t.append(" – Ohne Echtzeitdaten auschecken?"),t.data("force",!0)})}),$(".action-undo").click(function(){var t=$(this);tvly_run(t,{action:"undo",undo_id:t.data("id")})}),$(".action-cancelled-from").click(function(){var t=$(this);tvly_run(t,{action:"cancelled_from",station:t.data("station"),train:t.data("train")})}),$(".action-cancelled-to").click(function(){var t=$(this);tvly_run(t,{action:"cancelled_to",station:t.data("station"),force:!0})}),$(".action-delete").click(function(){var t=$(this),n={action:"delete",id:t.data("id"),checkin:t.data("checkin"),checkout:t.data("checkout")};really_delete=confirm("Diese Zugfahrt wirklich löschen? Der Eintrag wird sofort aus der Datenbank entfernt und kann nicht wiederhergestellt werden."),really_delete&&tvly_run(t,n)})});
|
||||
function tvly_run(t,a,n){var e='<i class="material-icons">error</i>',c=$('<div class="progress"><div class="indeterminate"></div></div>');t.hide(),t.after(c),$.post("/action",a,function(a){a.success?$(location).attr("href",a.redirect_to):(M.toast({html:e+" "+a.error}),c.remove(),n&&n(),t.append(" "+e),t.show())})}function tvly_update(){$.get("/ajax/status_card.html",function(t){$(".statuscol").html(t),tvly_reg_handlers(),setTimeout(tvly_update,15e3)}).fail(function(){setTimeout(tvly_update,15e3)})}function tvly_reg_handlers(){$(".action-checkin").click(function(){var t=$(this);tvly_run(t,{action:"checkin",station:t.data("station"),train:t.data("train")})}),$(".action-checkout").click(function(){var t=$(this),a={action:"checkout",station:t.data("station"),force:t.data("force")};tvly_run(t,a,function(){t.append(" – Ohne Echtzeitdaten auschecken?"),t.data("force",!0)})}),$(".action-undo").click(function(){var t=$(this);tvly_run(t,{action:"undo",undo_id:t.data("id")})}),$(".action-cancelled-from").click(function(){var t=$(this);tvly_run(t,{action:"cancelled_from",station:t.data("station"),train:t.data("train")})}),$(".action-cancelled-to").click(function(){var t=$(this);tvly_run(t,{action:"cancelled_to",station:t.data("station"),force:!0})}),$(".action-delete").click(function(){var t=$(this),a={action:"delete",id:t.data("id"),checkin:t.data("checkin"),checkout:t.data("checkout")};really_delete=confirm("Diese Zugfahrt wirklich löschen? Der Eintrag wird sofort aus der Datenbank entfernt und kann nicht wiederhergestellt werden."),really_delete&&tvly_run(t,a)})}$(document).ready(function(){tvly_reg_handlers(),$(".statuscol .autorefresh").length&&setTimeout(tvly_update,15e3)});
|
||||
|
|
27
templates/_cancelled.html.ep
Normal file
27
templates/_cancelled.html.ep
Normal file
|
@ -0,0 +1,27 @@
|
|||
<div class="card yellow lighten-4">
|
||||
<div class="card-content">
|
||||
<span class="card-title">Zugausfall dokumentieren</span>
|
||||
<p>Prinzipiell wärest du nun eingecheckt in
|
||||
<%= $status->{train_type} %> <%= $status->{train_no} %>
|
||||
ab <%= $status->{station_name} %>, doch dieser Zug fällt aus.
|
||||
</p>
|
||||
<p>Falls du den Zugausfall z.B. für ein Fahrgastrechteformular
|
||||
dokumentieren möchtest, wähle bitte jetzt deine geplante
|
||||
Zielstation aus. Achtung: Momentan wird dabei keine
|
||||
Soll-Ankunftszeit gespeichert, das zu beheben steht auf
|
||||
der Todoliste.</p>
|
||||
<table>
|
||||
<tbody>
|
||||
% my $is_after = 0;
|
||||
% for my $station (@{$status->{route_after}}) {
|
||||
<tr><td><a class="action-cancelled-to" data-station="<%= $station %>"><%= $station %></a></td></tr>
|
||||
% }
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="card-action">
|
||||
<a class="action-undo" data-id="in_transit">
|
||||
<i class="material-icons">undo</i> Checkinversuch Rückgängig?
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
85
templates/_checked_in.html.ep
Normal file
85
templates/_checked_in.html.ep
Normal file
|
@ -0,0 +1,85 @@
|
|||
<div class="card green darken-4 autorefresh">
|
||||
<div class="card-content white-text">
|
||||
<span class="card-title">Eingecheckt</span>
|
||||
<p>
|
||||
In <b><%= $status->{train_type} %> <%= $status->{train_no} %></b>
|
||||
% if ($status->{arr_name}) {
|
||||
von <b><%= $status->{dep_name} %></b> nach <b><%= $status->{arr_name} %></b>.
|
||||
% }
|
||||
% else {
|
||||
ab <b><%= $status->{dep_name} %></b>.
|
||||
% }
|
||||
</p>
|
||||
<p>
|
||||
<b><%= $status->{real_departure}->strftime('%H:%M') %></b>
|
||||
% if ($status->{real_departure}->epoch != $status->{sched_departure}->epoch) {
|
||||
(<%= sprintf('%+d', ($status->{real_departure}->epoch - $status->{sched_departure}->epoch)/60) %>)
|
||||
% }
|
||||
→
|
||||
% if ($status->{real_arrival}->epoch) {
|
||||
<b><%= $status->{real_arrival}->strftime('%H:%M') %></b>
|
||||
% if ($status->{real_arrival}->epoch != $status->{sched_arrival}->epoch) {
|
||||
(<%= sprintf('%+d', ($status->{real_arrival}->epoch - $status->{sched_arrival}->epoch)/60) %>)
|
||||
% }
|
||||
% }
|
||||
% else {
|
||||
unbekannt
|
||||
% }
|
||||
</p>
|
||||
<p>
|
||||
<div class="center">
|
||||
% if ($status->{departure_countdown} > 120) {
|
||||
Abfahrt in <%= int($status->{departure_countdown} / 60) %> Minuten
|
||||
% }
|
||||
% elsif ($status->{arrival_countdown}) {
|
||||
% if ($status->{arrival_countdown} > 0) {
|
||||
Ankunft in <%= int($status->{arrival_countdown} / 60) %>
|
||||
Minute<%= int($status->{arrival_countdown} / 60) == 1 ? '' : 'n' %>
|
||||
% }
|
||||
% else {
|
||||
Ziel erreicht
|
||||
% }
|
||||
% }
|
||||
% elsif ($status->{arr_name}) {
|
||||
Ankunft in mehr als zwei Stunden
|
||||
% }
|
||||
</div>
|
||||
<div class="progress green darken-3" style="height: 1ex;">
|
||||
<div class="determinate white" style="width: <%= sprintf('%.2f', 100 * $status->{journey_completion}); %>%;"></div>
|
||||
</div>
|
||||
</p>
|
||||
% if ($status->{arr_name}) {
|
||||
<p>Zielstation ändern?</p>
|
||||
% }
|
||||
% else {
|
||||
<p>Zielstation wählen:</p>
|
||||
% }
|
||||
<table>
|
||||
<tbody>
|
||||
% my $is_after = 0;
|
||||
% for my $station (@{$status->{route_after}}) {
|
||||
% if ($status->{arr_name} and $station eq $status->{arr_name}) {
|
||||
<tr><td><b><a class="action-checkout" data-station="<%= $station %>"><%= $station %></a></b></td></tr>
|
||||
% }
|
||||
% else {
|
||||
<tr><td><a class="action-checkout" data-station="<%= $station %>"><%= $station %></a></td></tr>
|
||||
% }
|
||||
% }
|
||||
</tbody>
|
||||
</table>
|
||||
% if ($status->{arr_name}) {
|
||||
<p>
|
||||
Falls das Backend ausgefallen ist oder der Zug aus anderen
|
||||
Gründen verloren ging: <a class="action-checkout"
|
||||
data-force="1" data-station="<%= $status->{arr_name}
|
||||
%>">Ohne Echtzeitdaten in <%= $status->{arr_name} %>
|
||||
auschecken</a>.
|
||||
</p>
|
||||
% }
|
||||
</div>
|
||||
<div class="card-action">
|
||||
<a class="action-undo" data-id="in_transit">
|
||||
<i class="material-icons">undo</i> Checkin Rückgängig?
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
12
templates/_checked_out.html.ep
Normal file
12
templates/_checked_out.html.ep
Normal file
|
@ -0,0 +1,12 @@
|
|||
<div class="card grey darken-4">
|
||||
<div class="card-content white-text">
|
||||
<span class="card-title">Ausgecheckt</span>
|
||||
<p>Aus <%= $status->{train_type} %> <%= $status->{train_no} %>
|
||||
bis <%= $status->{arr_name} %></p>
|
||||
</div>
|
||||
<div class="card-action">
|
||||
<a class="action-undo" data-id="<%= $status->{journey_id} %>">
|
||||
<i class="material-icons">undo</i> Rückgängig?
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
|
@ -16,18 +16,7 @@
|
|||
</div>
|
||||
% }
|
||||
% elsif ($status->{timestamp_delta} < 180) {
|
||||
<div class="card grey darken-4">
|
||||
<div class="card-content white-text">
|
||||
<span class="card-title">Ausgecheckt</span>
|
||||
<p>Aus <%= $status->{train_type} %> <%= $status->{train_no} %>
|
||||
bis <%= $status->{arr_name} %></p>
|
||||
</div>
|
||||
<div class="card-action">
|
||||
<a class="action-undo" data-id="<%= $status->{journey_id} %>">
|
||||
<i class="material-icons">undo</i> Rückgängig?
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
%= include '_checked_out', status => $status;
|
||||
% }
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -12,94 +12,10 @@
|
|||
</div>
|
||||
% }
|
||||
<div class="row">
|
||||
<div class="col s12">
|
||||
<div class="col s12 statuscol">
|
||||
% my $status = get_user_status();
|
||||
% if ($status->{checked_in}) {
|
||||
<div class="card green darken-4">
|
||||
<div class="card-content white-text">
|
||||
<span class="card-title">Eingecheckt</span>
|
||||
<p>
|
||||
In <b><%= $status->{train_type} %> <%= $status->{train_no} %></b>
|
||||
% if ($status->{arr_name}) {
|
||||
von <b><%= $status->{dep_name} %></b> nach <b><%= $status->{arr_name} %></b>.
|
||||
% }
|
||||
% else {
|
||||
ab <b><%= $status->{dep_name} %></b>.
|
||||
% }
|
||||
</p>
|
||||
<p>
|
||||
<b><%= $status->{real_departure}->strftime('%H:%M') %></b>
|
||||
% if ($status->{real_departure}->epoch != $status->{sched_departure}->epoch) {
|
||||
(<%= sprintf('%+d', ($status->{real_departure}->epoch - $status->{sched_departure}->epoch)/60) %>)
|
||||
% }
|
||||
→
|
||||
% if ($status->{real_arrival}->epoch) {
|
||||
<b><%= $status->{real_arrival}->strftime('%H:%M') %></b>
|
||||
% if ($status->{real_arrival}->epoch != $status->{sched_arrival}->epoch) {
|
||||
(<%= sprintf('%+d', ($status->{real_arrival}->epoch - $status->{sched_arrival}->epoch)/60) %>)
|
||||
% }
|
||||
% }
|
||||
% else {
|
||||
unbekannt
|
||||
% }
|
||||
</p>
|
||||
<p>
|
||||
<div class="center">
|
||||
% if ($status->{departure_countdown} > 120) {
|
||||
Abfahrt in <%= int($status->{departure_countdown} / 60) %> Minuten
|
||||
% }
|
||||
% elsif ($status->{arrival_countdown}) {
|
||||
% if ($status->{arrival_countdown} > 0) {
|
||||
Ankunft in <%= int($status->{arrival_countdown} / 60) %>
|
||||
Minute<%= int($status->{arrival_countdown} / 60) == 1 ? '' : 'n' %>
|
||||
% }
|
||||
% else {
|
||||
Ziel erreicht
|
||||
% }
|
||||
% }
|
||||
% elsif ($status->{arr_name}) {
|
||||
Ankunft in mehr als zwei Stunden
|
||||
% }
|
||||
</div>
|
||||
<div class="progress green darken-3" style="height: 1ex;">
|
||||
<div class="determinate white" style="width: <%= sprintf('%.2f', 100 * $status->{journey_completion}); %>%;"></div>
|
||||
</div>
|
||||
</p>
|
||||
% if ($status->{arr_name}) {
|
||||
<p>Zielstation ändern?</p>
|
||||
% }
|
||||
% else {
|
||||
<p>Zielstation wählen:</p>
|
||||
% }
|
||||
<table>
|
||||
<tbody>
|
||||
% my $is_after = 0;
|
||||
% for my $station (@{$status->{route_after}}) {
|
||||
% if ($status->{arr_name} and $station eq $status->{arr_name}) {
|
||||
<tr><td><b><a class="action-checkout" data-station="<%= $station %>"><%= $station %></a></b></td></tr>
|
||||
% }
|
||||
% else {
|
||||
<tr><td><a class="action-checkout" data-station="<%= $station %>"><%= $station %></a></td></tr>
|
||||
% }
|
||||
% }
|
||||
</tbody>
|
||||
</table>
|
||||
% if ($status->{arr_name}) {
|
||||
<p>
|
||||
Falls das Backend ausgefallen ist oder der Zug aus anderen
|
||||
Gründen verloren ging: <a class="action-checkout"
|
||||
data-force="1" data-station="<%= $status->{arr_name}
|
||||
%>">Ohne Echtzeitdaten in <%= $status->{arr_name} %>
|
||||
auschecken</a>.
|
||||
</p>
|
||||
% }
|
||||
</div>
|
||||
<div class="card-action">
|
||||
<a class="action-undo" data-id="in_transit">
|
||||
<i class="material-icons">undo</i> Checkin Rückgängig?
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
%= include '_checked_in', status => $status;
|
||||
% }
|
||||
% elsif ($status->{cancelled}) {
|
||||
<div class="card yellow lighten-4">
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="theme-color" content="#673ab7">
|
||||
% my $av = 'v6'; # asset version
|
||||
% my $av = 'v7'; # asset version
|
||||
%= stylesheet "/static/${av}/css/materialize.min.css"
|
||||
%= stylesheet "/static/${av}/css/material-icons.css"
|
||||
%= stylesheet "/static/${av}/css/local.css"
|
||||
|
|
Loading…
Reference in a new issue