diff options
author | Daniel Friesel <derf@finalrewind.org> | 2019-05-19 10:32:57 +0200 |
---|---|---|
committer | Daniel Friesel <derf@finalrewind.org> | 2019-05-19 10:32:57 +0200 |
commit | d9d3aac79200ca7d896d753c897e1651517ecf36 (patch) | |
tree | 87194b7a8b67b7b09bd2dc357e5239099dd60430 | |
parent | 7960114f71720f2c2fa86e74be4b80812edaef36 (diff) |
allow checkin from connections view
-rwxr-xr-x | lib/Travelynx.pm | 19 | ||||
-rwxr-xr-x | lib/Travelynx/Controller/Traveling.pm | 16 | ||||
-rw-r--r-- | public/service-worker.js | 26 | ||||
-rw-r--r-- | public/static/css/material-icons.css | 8 | ||||
-rw-r--r-- | public/static/js/travelynx-actions.js | 1 | ||||
-rw-r--r-- | public/static/js/travelynx-actions.min.js | 2 | ||||
-rw-r--r-- | public/static/manifest.json | 12 | ||||
l--------- | public/static/v24 (renamed from public/static/v22) | 0 | ||||
-rw-r--r-- | templates/_checked_in.html.ep | 30 | ||||
-rw-r--r-- | templates/_checked_out.html.ep | 5 | ||||
-rw-r--r-- | templates/_connections.html.ep | 60 | ||||
-rw-r--r-- | templates/layouts/default.html.ep | 2 |
12 files changed, 121 insertions, 60 deletions
diff --git a/lib/Travelynx.pm b/lib/Travelynx.pm index 9e00d3f..ff75898 100755 --- a/lib/Travelynx.pm +++ b/lib/Travelynx.pm @@ -176,6 +176,12 @@ sub startup { ); $self->helper( + 'now' => sub { + return DateTime->now( time_zone => 'Europe/Berlin' ); + } + ); + + $self->helper( 'numify_skipped_stations' => sub { my ( $self, $count ) = @_; @@ -1489,7 +1495,7 @@ sub startup { my $uid = $opt{uid} // $self->current_user->{id}; my $threshold = $opt{threshold} // DateTime->now( time_zone => 'Europe/Berlin' ) - ->subtract( weeks => 60 ); + ->subtract( weeks => 6 ); my $db = $opt{db} // $self->pg->db; my $journey = $db->select( 'in_transit', ['checkout_station_id'], @@ -1504,7 +1510,7 @@ sub startup { }, { limit => 1, - order_by => { -desc => 'real_dep_ts' } + order_by => { -desc => 'real_departure' } } )->hash; } @@ -1547,11 +1553,14 @@ sub startup { } my @destinations = $self->get_connection_targets(%opt); - my $stationboard - = $self->get_departures( $status->{arr_ds100}, 0, 60 ); - @destinations = grep { $_ ne $status->{dep_name} } @destinations; + if ( not @destinations ) { + return; + } + + my $stationboard + = $self->get_departures( $status->{arr_ds100}, 0, 60 ); if ( $stationboard->{errstr} ) { return; } diff --git a/lib/Travelynx/Controller/Traveling.pm b/lib/Travelynx/Controller/Traveling.pm index 3d2bb0c..4e4b069 100755 --- a/lib/Travelynx/Controller/Traveling.pm +++ b/lib/Travelynx/Controller/Traveling.pm @@ -145,6 +145,7 @@ sub log_action { my ( $train, $error ) = $self->checkin( $params->{station}, $params->{train} ); + my $destination = $params->{dest}; if ($error) { $self->render( @@ -154,7 +155,7 @@ sub log_action { }, ); } - else { + elsif ( not $destination ) { $self->render( json => { success => 1, @@ -162,6 +163,19 @@ sub log_action { }, ); } + else { + # Silently ignore errors -- if they are permanent, the user will see + # them when selecting the destination manually. + my ( $still_checked_in, undef ) + = $self->checkout( $destination, 0 ); + my $station_link = '/s/' . $destination; + $self->render( + json => { + success => 1, + redirect_to => $still_checked_in ? '/' : $station_link, + }, + ); + } } elsif ( $params->{action} eq 'checkout' ) { my ( $still_checked_in, $error ) diff --git a/public/service-worker.js b/public/service-worker.js index 5a8ac94..0befced 100644 --- a/public/service-worker.js +++ b/public/service-worker.js @@ -1,19 +1,19 @@ -const CACHE_NAME = 'static-cache-v23'; +const CACHE_NAME = 'static-cache-v24'; const FILES_TO_CACHE = [ '/favicon.ico', '/offline.html', - '/static/v23/css/light.min.css', - '/static/v23/css/dark.min.css', - '/static/v23/css/material-icons.css', - '/static/v23/css/local.css', - '/static/v23/fonts/MaterialIcons-Regular.woff2', - '/static/v23/fonts/MaterialIcons-Regular.woff', - '/static/v23/fonts/MaterialIcons-Regular.ttf', - '/static/v23/js/jquery-3.4.1.min.js', - '/static/v23/js/materialize.min.js', - '/static/v23/js/travelynx-actions.min.js', - '/static/v23/js/autocomplete.min.js', - '/static/v23/js/geolocation.min.js', + '/static/v24/css/light.min.css', + '/static/v24/css/dark.min.css', + '/static/v24/css/material-icons.css', + '/static/v24/css/local.css', + '/static/v24/fonts/MaterialIcons-Regular.woff2', + '/static/v24/fonts/MaterialIcons-Regular.woff', + '/static/v24/fonts/MaterialIcons-Regular.ttf', + '/static/v24/js/jquery-3.4.1.min.js', + '/static/v24/js/materialize.min.js', + '/static/v24/js/travelynx-actions.min.js', + '/static/v24/js/autocomplete.min.js', + '/static/v24/js/geolocation.min.js', ]; self.addEventListener('install', (evt) => { diff --git a/public/static/css/material-icons.css b/public/static/css/material-icons.css index 1aa0681..18625d5 100644 --- a/public/static/css/material-icons.css +++ b/public/static/css/material-icons.css @@ -2,12 +2,12 @@ font-family: 'Material Icons'; font-style: normal; font-weight: 400; - src: url(/static/v23/fonts/MaterialIcons-Regular.eot); /* For IE6-8 */ + src: url(/static/v24/fonts/MaterialIcons-Regular.eot); /* For IE6-8 */ src: local('Material Icons'), local('MaterialIcons-Regular'), - url(/static/v23/fonts/MaterialIcons-Regular.woff2) format('woff2'), - url(/static/v23/fonts/MaterialIcons-Regular.woff) format('woff'), - url(/static/v23/fonts/MaterialIcons-Regular.ttf) format('truetype'); + url(/static/v24/fonts/MaterialIcons-Regular.woff2) format('woff2'), + url(/static/v24/fonts/MaterialIcons-Regular.woff) format('woff'), + url(/static/v24/fonts/MaterialIcons-Regular.ttf) format('truetype'); } .material-icons { diff --git a/public/static/js/travelynx-actions.js b/public/static/js/travelynx-actions.js index b4a6b90..deb010a 100644 --- a/public/static/js/travelynx-actions.js +++ b/public/static/js/travelynx-actions.js @@ -84,6 +84,7 @@ function tvly_reg_handlers() { action: 'checkin', station: link.data('station'), train: link.data('train'), + dest: link.data('dest'), }; tvly_run(link, req); }); diff --git a/public/static/js/travelynx-actions.min.js b/public/static/js/travelynx-actions.min.js index 751800e..9813f84 100644 --- a/public/static/js/travelynx-actions.min.js +++ b/public/static/js/travelynx-actions.min.js @@ -1 +1 @@ -var j_duration=0,j_arrival=0;function upd_journey_data(){$(".countdown").each(function(){j_duration=$(this).data("duration"),j_arrival=$(this).data("arrival")})}function upd_countdown(){var t=Date.now()/1e3;0<j_arrival&&(t<j_arrival?$(".countdown").text("Ankunft in "+Math.round((j_arrival-t)/60)+" Minuten"):$(".countdown").text("Ziel erreicht"))}function tvly_run(a,t,e){var n='<i class="material-icons">error</i>',i=$('<div class="progress"><div class="indeterminate"></div></div>');a.hide(),a.after(i),$.post("/action",t,function(t){t.success?$(location).attr("href",t.redirect_to):(M.toast({html:n+" "+t.error}),i.remove(),e&&e(),a.append(" "+n),a.show())})}function tvly_update(){$.get("/ajax/status_card.html",function(t){$(".statuscol").html(t),tvly_reg_handlers(),upd_journey_data(),setTimeout(tvly_update,4e4)}).fail(function(){$(".sync-failed-marker").css("display","block"),upd_countdown(),setTimeout(tvly_update,5e3)})}function tvly_update_public(){var t;$(".publicstatuscol").each(function(){t=$(this).data("user")}),$.get("/ajax/status/"+t+".html",function(t){$(".publicstatuscol").html(t),upd_journey_data(),setTimeout(tvly_update_public,4e4)}).fail(function(){$(".sync-failed-marker").css("display","block"),upd_countdown(),setTimeout(tvly_update_public,5e3)})}function tvly_journey_progress(){var t=Date.now()/1e3,a=0;0<j_duration&&((a=1-(j_arrival-t)/j_duration)<0&&(a=0),1<a&&(a=1),$(".progress .determinate").css("width",100*a+"%"),setTimeout(tvly_journey_progress,5e3))}function tvly_reg_handlers(){$(".action-checkin").click(function(){var t=$(this),a={action:"checkin",station:t.data("station"),train:t.data("train")};tvly_run(t,a)}),$(".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),a={action:"undo",undo_id:t.data("id")};tvly_run(t,a)}),$(".action-cancelled-from").click(function(){var t=$(this),a={action:"cancelled_from",station:t.data("station"),train:t.data("train")};tvly_run(t,a)}),$(".action-cancelled-to").click(function(){var t=$(this),a={action:"cancelled_to",station:t.data("station"),force:!0};tvly_run(t,a)}),$(".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)}),$(".action-share").click(function(){navigator.share&&(shareObj={text:$(this).data("text")},$(this).data("url")&&(shareObj.url=$(this).data("url")),navigator.share(shareObj))}),$(".action-share").length&&!navigator.share&&$(".action-share").css("display","none")}$(document).ready(function(){tvly_reg_handlers(),$(".statuscol .autorefresh").length&&(upd_journey_data(),setTimeout(tvly_update,4e4),setTimeout(tvly_journey_progress,5e3)),$(".publicstatuscol .autorefresh").length&&(upd_journey_data(),setTimeout(tvly_update_public,4e4),setTimeout(tvly_journey_progress,5e3)),$("a[href]").click(function(){$("nav .preloader-wrapper").addClass("active")})}); +function upd_journey_data(){$(".countdown").each(function(){j_duration=$(this).data("duration"),j_arrival=$(this).data("arrival")})}function upd_countdown(){var t=Date.now()/1e3;j_arrival>0&&(j_arrival>t?$(".countdown").text("Ankunft in "+Math.round((j_arrival-t)/60)+" Minuten"):$(".countdown").text("Ziel erreicht"))}function tvly_run(t,a,e){var n='<i class="material-icons">error</i>',i=$('<div class="progress"><div class="indeterminate"></div></div>');t.hide(),t.after(i),$.post("/action",a,function(a){a.success?$(location).attr("href",a.redirect_to):(M.toast({html:n+" "+a.error}),i.remove(),e&&e(),t.append(" "+n),t.show())})}function tvly_update(){$.get("/ajax/status_card.html",function(t){$(".statuscol").html(t),tvly_reg_handlers(),upd_journey_data(),setTimeout(tvly_update,4e4)}).fail(function(){$(".sync-failed-marker").css("display","block"),upd_countdown(),setTimeout(tvly_update,5e3)})}function tvly_update_public(){var t;$(".publicstatuscol").each(function(){t=$(this).data("user")}),$.get("/ajax/status/"+t+".html",function(t){$(".publicstatuscol").html(t),upd_journey_data(),setTimeout(tvly_update_public,4e4)}).fail(function(){$(".sync-failed-marker").css("display","block"),upd_countdown(),setTimeout(tvly_update_public,5e3)})}function tvly_journey_progress(){var t=Date.now()/1e3,a=0;j_duration>0&&(a=1-(j_arrival-t)/j_duration,a<0&&(a=0),a>1&&(a=1),$(".progress .determinate").css("width",100*a+"%"),setTimeout(tvly_journey_progress,5e3))}function tvly_reg_handlers(){$(".action-checkin").click(function(){var t=$(this);tvly_run(t,{action:"checkin",station:t.data("station"),train:t.data("train"),dest:t.data("dest")})}),$(".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)}),$(".action-share").click(function(){navigator.share&&(shareObj={text:$(this).data("text")},$(this).data("url")&&(shareObj.url=$(this).data("url")),navigator.share(shareObj))}),$(".action-share").length&&!navigator.share&&$(".action-share").css("display","none")}var j_duration=0,j_arrival=0;$(document).ready(function(){tvly_reg_handlers(),$(".statuscol .autorefresh").length&&(upd_journey_data(),setTimeout(tvly_update,4e4),setTimeout(tvly_journey_progress,5e3)),$(".publicstatuscol .autorefresh").length&&(upd_journey_data(),setTimeout(tvly_update_public,4e4),setTimeout(tvly_journey_progress,5e3)),$("a[href]").click(function(){$("nav .preloader-wrapper").addClass("active")})}); diff --git a/public/static/manifest.json b/public/static/manifest.json index 53b23be..ed04b30 100644 --- a/public/static/manifest.json +++ b/public/static/manifest.json @@ -3,27 +3,27 @@ "short_name": "Travelynx", "scope": "/", "icons": [{ - "src": "/static/v23/icons/icon-128x128.png", + "src": "/static/v24/icons/icon-128x128.png", "sizes": "128x128", "type": "image/png" }, { - "src": "/static/v23/icons/icon-144x144.png", + "src": "/static/v24/icons/icon-144x144.png", "sizes": "144x144", "type": "image/png" }, { - "src": "/static/v23/icons/icon-152x152.png", + "src": "/static/v24/icons/icon-152x152.png", "sizes": "152x152", "type": "image/png" }, { - "src": "/static/v23/icons/icon-192x192.png", + "src": "/static/v24/icons/icon-192x192.png", "sizes": "192x192", "type": "image/png" }, { - "src": "/static/v23/icons/icon-256x256.png", + "src": "/static/v24/icons/icon-256x256.png", "sizes": "256x256", "type": "image/png" }, { - "src": "/static/v23/icons/icon-512x512.png", + "src": "/static/v24/icons/icon-512x512.png", "sizes": "512x512", "type": "image/png" }], diff --git a/public/static/v22 b/public/static/v24 index 945c9b4..945c9b4 120000 --- a/public/static/v22 +++ b/public/static/v24 diff --git a/templates/_checked_in.html.ep b/templates/_checked_in.html.ep index 39bc1e3..d5b14e5 100644 --- a/templates/_checked_in.html.ep +++ b/templates/_checked_in.html.ep @@ -79,35 +79,7 @@ % } % if (defined $journey->{arrival_countdown} and $journey->{arrival_countdown} < (20*60)) { % if (my @connections = get_connecting_trains()) { - <span class="card-title" style="margin-top: 2ex;">Verbindungen</span> - <div class="hide-on-med-and-up"><table><tbody> - % for my $res (@connections) { - % my ($train, $via) = @{$res}; - <tr> - <td><%= $train->line %></td> - <td><%= $via %></td> - <td><%= $train->departure->strftime('%H:%M') %> - % if ($train->departure_delay) { - %= sprintf('(%+d)', $train->departure_delay) - % } - <br/>Gleis <%= $train->platform %></td> - </tr> - % } - </tbody></table></div> - <div class="hide-on-small-only"><table><tbody> - % for my $res (@connections) { - % my ($train, $via) = @{$res}; - <tr> - <td><%= $train->line %></td> - <td><%= $via %></td> - <td><%= $train->departure->strftime('%H:%M') %> - % if ($train->departure_delay) { - %= sprintf('(%+d)', $train->departure_delay) - % } - </td><td>Gleis <%= $train->platform %></td> - </tr> - % } - </tbody></table></div> + %= include '_connections', connections => \@connections, checkin_from => $journey->{arrival_countdown} < 0 ? $journey->{arr_ds100} : undef; % } % } % if (defined $journey->{arrival_countdown} and $journey->{arrival_countdown} <= 0) { diff --git a/templates/_checked_out.html.ep b/templates/_checked_out.html.ep index 9c7ff48..18b613b 100644 --- a/templates/_checked_out.html.ep +++ b/templates/_checked_out.html.ep @@ -3,6 +3,11 @@ <span class="card-title">Ausgecheckt</span> <p>Aus <%= $journey->{train_type} %> <%= $journey->{train_no} %> bis <a href="/s/<%= $journey->{arr_ds100} %>"><%= $journey->{arr_name} %></a></p> + % if (now()->epoch - $journey->{timestamp}->epoch < (30*60)) { + % if (my @connections = get_connecting_trains()) { + %= include '_connections', connections => \@connections, checkin_from => $journey->{arr_ds100}; + % } + % } </div> <div class="card-action"> <a class="action-undo" data-id="<%= $journey->{journey_id} %>"> diff --git a/templates/_connections.html.ep b/templates/_connections.html.ep new file mode 100644 index 0000000..1c7f003 --- /dev/null +++ b/templates/_connections.html.ep @@ -0,0 +1,60 @@ +<span class="card-title" style="margin-top: 2ex;">Verbindungen</span> +% if ($checkin_from) { + <p>Zug auswählen zum Einchecken mit Zielwahl.</p> +% } +<div class="hide-on-med-and-up"><table><tbody> + % for my $res (@{$connections}) { + % my ($train, $via) = @{$res}; + <tr> + <td> + % if ($checkin_from) { + <a class="action-checkin" data-station="<%= $checkin_from %>" data-train="<%= $train->train_id %>" data-dest="<%= $via %>"><%= $train->line %></a> + % } + % else { + %= $train->line + % } + </td> + <td> + % if ($checkin_from) { + <a class="action-checkin" data-station="<%= $checkin_from %>" data-train="<%= $train->train_id %>" data-dest="<%= $via %>"><%= $via %></a> + % } + % else { + %= $via + % } + </td> + <td><%= $train->departure->strftime('%H:%M') %> + % if ($train->departure_delay) { + %= sprintf('(%+d)', $train->departure_delay) + % } + <br/>Gleis <%= $train->platform %></td> + </tr> + % } +</tbody></table></div> +<div class="hide-on-small-only"><table><tbody> + % for my $res (@{$connections}) { + % my ($train, $via) = @{$res}; + <tr> + <td> + % if ($checkin_from) { + <a class="action-checkin" data-station="<%= $checkin_from %>" data-train="<%= $train->train_id %>" data-dest="<%= $via %>"><%= $train->line %></a> + % } + % else { + %= $train->line + % } + </td> + <td> + % if ($checkin_from) { + <a class="action-checkin" data-station="<%= $checkin_from %>" data-train="<%= $train->train_id %>" data-dest="<%= $via %>"><%= $via %></a> + % } + % else { + %= $via + % } + </td> + <td><%= $train->departure->strftime('%H:%M') %> + % if ($train->departure_delay) { + %= sprintf('(%+d)', $train->departure_delay) + % } + </td><td>Gleis <%= $train->platform %></td> + </tr> + % } +</tbody></table></div> diff --git a/templates/layouts/default.html.ep b/templates/layouts/default.html.ep index 4c94c50..ab2ce82 100644 --- a/templates/layouts/default.html.ep +++ b/templates/layouts/default.html.ep @@ -9,7 +9,7 @@ <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <meta name="apple-mobile-web-app-title" content="Travelynx"> - % my $av = 'v23'; # asset version + % my $av = 'v24'; # asset version <link rel="icon" type="image/png" href="/static/<%= $av %>/icons/icon-16x16.png" sizes="16x16"> <link rel="icon" type="image/png" href="/static/<%= $av %>/icons/icon-32x32.png" sizes="32x32"> <link rel="icon" type="image/png" href="/static/<%= $av %>/icons/icon-96x96.png" sizes="96x96"> |