diff options
| -rwxr-xr-x | index.pl | 84 | ||||
| -rw-r--r-- | public/static/css/local.css | 4 | ||||
| -rw-r--r-- | public/static/js/travelynx-actions.js | 20 | ||||
| -rw-r--r-- | public/static/js/travelynx-actions.min.js | 2 | ||||
| -rw-r--r-- | templates/departures.html.ep | 14 | ||||
| -rw-r--r-- | templates/landingpage.html.ep | 27 | ||||
| -rw-r--r-- | templates/layouts/default.html.ep | 2 | 
7 files changed, 130 insertions, 23 deletions
| @@ -33,11 +33,13 @@ my $cache_iris_rt = Cache::File->new(  my $dbname = $ENV{TRAVELYNX_DB_FILE} // 'travelynx.sqlite';  my %action_type = ( -	checkin  => 1, -	checkout => 2, -	undo     => 3, +	checkin        => 1, +	checkout       => 2, +	undo           => 3, +	cancelled_from => 4, +	cancelled_to   => 5,  ); -my @action_types = (qw(checkin checkout undo)); +my @action_types = (qw(checkin checkout undo cancelled_from cancelled_to));  my %token_type   = (  	status  => 1,  	history => 2, @@ -476,7 +478,9 @@ sub get_station {  }  helper 'checkin' => sub { -	my ( $self, $station, $train_id ) = @_; +	my ( $self, $station, $train_id, $action_id ) = @_; + +	$action_id //= $action_type{checkin};  	my $status = get_departures($station);  	if ( $status->{errstr} ) { @@ -504,10 +508,17 @@ helper 'checkin' => sub {               # XXX same workaround: We can't checkin immediately after checkout.  				sleep(1);  			} +			elsif ( $user->{cancelled} ) { + +				# Same +				sleep(1); +				$self->cancelled_to($station); +				sleep(1); +			}  			my $success = $self->app->action_query->execute(  				$self->current_user->{id}, -				$action_type{checkin}, +				$action_id,  				$self->get_station_id(  					ds100 => $status->{station_ds100},  					name  => $status->{station_name} @@ -563,13 +574,15 @@ helper 'undo' => sub {  };  helper 'checkout' => sub { -	my ( $self, $station, $force ) = @_; +	my ( $self, $station, $force, $action_id ) = @_; + +	$action_id //= $action_type{checkout};  	my $status   = get_departures( $station, 180 );  	my $user     = $self->get_user_status;  	my $train_id = $user->{train_id}; -	if ( not $user->{checked_in} ) { +	if ( not $user->{checked_in} and not $user->{cancelled} ) {  		return 'You are not checked into any train';  	}  	if ( $status->{errstr} and not $force ) { @@ -582,7 +595,7 @@ helper 'checkout' => sub {  		if ($force) {  			my $success = $self->app->action_query->execute(  				$self->current_user->{id}, -				$action_type{checkout}, +				$action_id,  				$self->get_station_id(  					ds100 => $status->{station_ds100},  					name  => $status->{station_name} @@ -892,6 +905,7 @@ helper 'get_user_status' => sub {  		}  		return {  			checked_in      => ( $cols[0] == $action_type{checkin} ), +			cancelled       => ( $cols[0] == $action_type{cancelled_from} ),  			timestamp       => $action_ts,  			timestamp_delta => $now->epoch - $action_ts->epoch,  			sched_ts        => $sched_ts, @@ -1070,8 +1084,11 @@ get '/api/v0/:action/:token' => sub {  		$self->render(  			json => {  				deprecated => \0, -				checked_in => $status->{checked_in} ? \1 : \0, -				station    => { +				checked_in => ( +					     $status->{checked_in} +					  or $status->{cancelled} +				) ? \1 : \0, +				station => {  					ds100     => $status->{station_ds100},  					name      => $status->{station_name},  					uic       => $station_eva, @@ -1302,7 +1319,7 @@ post '/action' => sub {  	if ( $params->{action} eq 'checkin' ) {  		my ( $train, $error ) -		  = $self->checkin( $params->{station}, $params->{train}, ); +		  = $self->checkin( $params->{station}, $params->{train} );  		if ($error) {  			$self->render( @@ -1321,7 +1338,7 @@ post '/action' => sub {  		}  	}  	elsif ( $params->{action} eq 'checkout' ) { -		my $error = $self->checkout( $params->{station}, $params->{force}, ); +		my $error = $self->checkout( $params->{station}, $params->{force} );  		if ($error) {  			$self->render( @@ -1357,6 +1374,47 @@ post '/action' => sub {  			);  		}  	} +	elsif ( $params->{action} eq 'cancelled_from' ) { +		my ( undef, $error ) +		  = $self->checkin( $params->{station}, $params->{train}, +			$action_type{cancelled_from} ); + +		if ($error) { +			$self->render( +				json => { +					success => 0, +					error   => $error, +				}, +			); +		} +		else { +			$self->render( +				json => { +					success => 1, +				}, +			); +		} +	} +	elsif ( $params->{action} eq 'cancelled_to' ) { +		my $error = $self->checkout( $params->{station}, 1, +			$action_type{cancelled_to} ); + +		if ($error) { +			$self->render( +				json => { +					success => 0, +					error   => $error, +				}, +			); +		} +		else { +			$self->render( +				json => { +					success => 1, +				}, +			); +		} +	}  	else {  		$self->render(  			json => { diff --git a/public/static/css/local.css b/public/static/css/local.css index 7502b64..68f9ab1 100644 --- a/public/static/css/local.css +++ b/public/static/css/local.css @@ -1,6 +1,8 @@  .action-checkin,  .action-checkout, -.action-undo { +.action-undo, +.action-cancelled-from, +.action-cancelled-to {  	cursor: pointer;  } diff --git a/public/static/js/travelynx-actions.js b/public/static/js/travelynx-actions.js index 0a3d092..d47df77 100644 --- a/public/static/js/travelynx-actions.js +++ b/public/static/js/travelynx-actions.js @@ -44,6 +44,24 @@ $(document).ready(function() {  		var req = {  			action: 'undo',  		}; -		tvly_run(link, req, window.location.href); +		tvly_run(link, req, '/'); +	}); +	$('.action-cancelled-from').click(function() { +		var link = $(this); +		var req = { +			action: 'cancelled_from', +			station: link.data('station'), +			train: link.data('train'), +		}; +		tvly_run(link, req, '/'); +	}); +	$('.action-cancelled-to').click(function() { +		var link = $(this); +		var req = { +			action: 'cancelled_to', +			station: link.data('station'), +			force: true, +		}; +		tvly_run(link, req, '/');  	});  }); diff --git a/public/static/js/travelynx-actions.min.js b/public/static/js/travelynx-actions.min.js index 9c37d8d..4fe0e76 100644 --- a/public/static/js/travelynx-actions.min.js +++ b/public/static/js/travelynx-actions.min.js @@ -1 +1 @@ -function tvly_run(n,t,i,a){var c='<i class="material-icons">error</i>',o=$('<div class="progress"><div class="indeterminate"></div></div>');n.hide(),n.after(o),$.post("/action",t,function(t){t.success?$(location).attr("href",i):(M.toast({html:c+" "+t.error}),o.remove(),a&&a(),n.append(" "+c),n.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,"/s/"+n.station,function(){t.append(" – Ohne Echtzeitdaten auschecken?"),t.data("force",!0)})}),$(".action-undo").click(function(){tvly_run($(this),{action:"undo"},window.location.href)})}); +function tvly_run(n,t,a,c){var i='<i class="material-icons">error</i>',o=$('<div class="progress"><div class="indeterminate"></div></div>');n.hide(),n.after(o),$.post("/action",t,function(t){t.success?$(location).attr("href",a):(M.toast({html:i+" "+t.error}),o.remove(),c&&c(),n.append(" "+i),n.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,"/s/"+n.station,function(){t.append(" – Ohne Echtzeitdaten auschecken?"),t.data("force",!0)})}),$(".action-undo").click(function(){tvly_run($(this),{action:"undo"},"/")}),$(".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},"/")})}); diff --git a/templates/departures.html.ep b/templates/departures.html.ep index ee87496..47c4872 100644 --- a/templates/departures.html.ep +++ b/templates/departures.html.ep @@ -52,22 +52,24 @@  			</thead>  			<tbody>  				% for my $result (@{$results}) { -					% my $class = ""; +					% my $td_class = ''; +					% my $link_class = 'action-checkin';  					% if ($result->departure_is_cancelled) { -						% $class = "cancelled"; +						% $td_class = "cancelled"; +						% $link_class = 'action-cancelled-from';  					% }  					<tr>  						<td> -							<a class="action-checkin" data-station="<%= $ds100 %>" data-train="<%= $result->train_id %>"> +							<a class="<%= $link_class %>" data-station="<%= $ds100 %>" data-train="<%= $result->train_id %>">  								<%= $result->line %>  							</a>  						</td> -						<td class="<%= $class %>"> -							<a class="action-checkin" data-station="<%= $ds100 %>" data-train="<%= $result->train_id %>"> +						<td class="<%= $td_class %>"> +							<a class="<%= $link_class %>" data-station="<%= $ds100 %>" data-train="<%= $result->train_id %>">  								<%= $result->destination %>  							</a>  						</td> -						<td class="<%= $class %>"><%= $result->departure->strftime('%H:%M') %> +						<td class="<%= $td_class %>"><%= $result->departure->strftime('%H:%M') %>  							% if ($result->departure_delay) {  								(+<%= $result->departure_delay %>)  							% } diff --git a/templates/landingpage.html.ep b/templates/landingpage.html.ep index dcc0083..83ad2a1 100644 --- a/templates/landingpage.html.ep +++ b/templates/landingpage.html.ep @@ -37,6 +37,33 @@  					</div>  				</div>  			% } +			% elsif ($status->{cancelled}) { +				<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. +							% if ($status->{timestamp_delta} < 3600) { +								<a class="action-undo"><i class="material-icons">undo</i> Checkinversuch rückgängig</a> +							% } +							</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> +			% }  			% else {  				<div class="card grey darken-4">  					<div class="card-content white-text"> diff --git a/templates/layouts/default.html.ep b/templates/layouts/default.html.ep index 8f5bdc2..2589788 100644 --- a/templates/layouts/default.html.ep +++ b/templates/layouts/default.html.ep @@ -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 = 'v3'; # asset version +	% my $av = 'v4'; # asset version  	%= stylesheet "/static/${av}/css/materialize.min.css"  	%= stylesheet "/static/${av}/css/material-icons.css"  	%= stylesheet "/static/${av}/css/local.css" | 
