diff options
| author | Birte Kristina Friesel <derf@finalrewind.org> | 2025-07-05 18:40:23 +0200 | 
|---|---|---|
| committer | Birte Kristina Friesel <derf@finalrewind.org> | 2025-07-05 18:40:23 +0200 | 
| commit | e5edf5b81567e1f79db64499c2ac3554d7508d81 (patch) | |
| tree | d445994d53e0600832ad1f438d2dcb607f8ab77a | |
| parent | 45771233e9db681a632aa4408cb17e379c55ff6b (diff) | |
| parent | 5a65ee90d146f19999837853e8311e5b03e31af8 (diff) | |
Merge branch 'date-inputs' of github.com:deingithub/travelynx
| -rwxr-xr-x | lib/Travelynx/Controller/Traveling.pm | 48 | ||||
| -rw-r--r-- | sass/src/dark/index.scss | 2 | ||||
| -rw-r--r-- | t/11-journey-stats.t | 20 | ||||
| -rw-r--r-- | t/12-journey-edit.t | 40 | ||||
| -rw-r--r-- | templates/add_intransit.html.ep | 12 | ||||
| -rw-r--r-- | templates/add_journey.html.ep | 18 | ||||
| -rw-r--r-- | templates/edit_journey.html.ep | 8 | ||||
| -rw-r--r-- | templates/history_by_month.html.ep | 2 | ||||
| -rw-r--r-- | templates/history_by_year.html.ep | 4 | ||||
| -rw-r--r-- | templates/history_map.html.ep | 8 | 
10 files changed, 89 insertions, 73 deletions
| diff --git a/lib/Travelynx/Controller/Traveling.pm b/lib/Travelynx/Controller/Traveling.pm index fd2abb1..74bb5c6 100755 --- a/lib/Travelynx/Controller/Traveling.pm +++ b/lib/Travelynx/Controller/Traveling.pm @@ -1745,13 +1745,12 @@ sub map_history {  	my $with_polyline = $route_type eq 'beeline' ? 0 : 1;  	my $parser = DateTime::Format::Strptime->new( -		pattern   => '%d.%m.%Y', +		pattern   => '%F',  		locale    => 'de_DE',  		time_zone => 'Europe/Berlin'  	); -	if (    $filter_from -		and $filter_from =~ m{ ^ (\d+) [.] (\d+) [.] (\d+) $ }x ) +	if ( $filter_from )  	{  		$filter_from = $parser->parse_datetime($filter_from);  	} @@ -1759,8 +1758,7 @@ sub map_history {  		$filter_from = undef;  	} -	if (    $filter_until -		and $filter_until =~ m{ ^ (\d+) [.] (\d+) [.] (\d+) $ }x ) +	if ( $filter_until )  	{  		$filter_until = $parser->parse_datetime($filter_until)->set(  			hour   => 23, @@ -2383,7 +2381,7 @@ sub edit_journey {  	if ( $self->param('action') and $self->param('action') eq 'save' ) {  		my $parser = DateTime::Format::Strptime->new( -			pattern   => '%d.%m.%Y %H:%M', +			pattern   => '%FT%H:%M',  			locale    => 'de_DE',  			time_zone => 'Europe/Berlin'  		); @@ -2486,7 +2484,7 @@ sub edit_journey {  	for my $key (qw(sched_departure rt_departure sched_arrival rt_arrival)) {  		if ( $journey->{$key} and $journey->{$key}->epoch ) {  			$self->param( -				$key => $journey->{$key}->strftime('%d.%m.%Y %H:%M') ); +				$key => $journey->{$key}->strftime('%FT%H:%M') );  		}  	} @@ -2518,7 +2516,7 @@ sub add_journey_form {  	if ( $self->param('action') and $self->param('action') eq 'save' ) {  		my $parser = DateTime::Format::Strptime->new( -			pattern   => '%d.%m.%Y %H:%M', +			pattern   => '%FT%H:%M',  			locale    => 'de_DE',  			time_zone => 'Europe/Berlin'  		); @@ -2619,7 +2617,12 @@ sub add_intransit_form {  	if ( $self->param('action') and $self->param('action') eq 'save' ) {  		my $parser = DateTime::Format::Strptime->new( -			pattern   => '%d.%m.%Y %H:%M', +			pattern   => '%FT%H:%M', +			locale    => 'de_DE', +			time_zone => 'Europe/Berlin' +		); +		my $time_parser = DateTime::Format::Strptime->new( +			pattern   => '%H:%M',  			locale    => 'de_DE',  			time_zone => 'Europe/Berlin'  		); @@ -2710,7 +2713,7 @@ sub add_intransit_form {  		if ( $trip{route} ) {  			my @unknown_stations; -			my $prev_epoch; +			my $prev_ts = $trip{sched_departure};  			for my $station ( @{ $trip{route} } ) {  				my $ts;  				my %station_data; @@ -2719,11 +2722,30 @@ sub add_intransit_form {  				  )  				{  					$station = $+{stop}; -					$ts      = $parser->parse_datetime( $+{timestamp} ); -					if ( $ts and $ts->epoch > $prev_epoch ) { +					# attempt to parse "07:08" short timestamp first +					$ts = $time_parser->parse_datetime( $+{timestamp} ); +					if ( $ts ) { +						# fill in last stop's (or at the first stop, our departure's) +						# date to complete the datetime +						$ts = $ts->set( +							year => $prev_ts->year, +							month => $prev_ts->month, +							day => $prev_ts->day +						); +						# if we go back in time with this, assume we went +						# over midnight and add a day, e.g. in case of a stop +						# at 23:00 followed by one at 01:30 +						if ($ts < $prev_ts) { +							$ts = $ts->add( days => 1 ); +						} +					} else { +						# do a full datetime parse +						$ts = $parser->parse_datetime( $+{timestamp} ); +					} +					if ( $ts and $ts >= $prev_ts ) {  						$station_data{sched_arr} = $ts->epoch;  						$station_data{sched_dep} = $ts->epoch; -						$prev_epoch              = $ts->epoch; +						$prev_ts              = $ts;  					}  					else {  						$self->render( diff --git a/sass/src/dark/index.scss b/sass/src/dark/index.scss index 28c615b..310a8a4 100644 --- a/sass/src/dark/index.scss +++ b/sass/src/dark/index.scss @@ -18,6 +18,8 @@ html {  input[type=email],  input[type=text],  input[type=password], +input[type=date], +input[type=datetime-local],  textarea {  	color: $off-black;  } diff --git a/t/11-journey-stats.t b/t/11-journey-stats.t index 4623402..3fc8724 100644 --- a/t/11-journey-stats.t +++ b/t/11-journey-stats.t @@ -82,11 +82,11 @@ $t->post_ok(  		action          => 'save',  		train           => 'RE 42 11238',  		dep_station     => 'EMSTP', -		sched_departure => '16.10.2018 17:36', -		rt_departure    => '16.10.2018 17:36', +		sched_departure => '2018-10-16T17:36', +		rt_departure    => '2018-10-16T17:36',  		arr_station     => 'EG', -		sched_arrival   => '16.10.2018 18:34', -		rt_arrival      => '16.10.2018 18:34', +		sched_arrival   => '2018-10-16T18:34', +		rt_arrival      => '2018-10-16T18:34',  		comment         => 'Passierschein A38',  	}  ); @@ -123,11 +123,11 @@ $t->post_ok(  		action          => 'save',  		train           => 'RE 42 11238',  		dep_station     => 'EMSTP', -		sched_departure => '16.11.2018 17:36', -		rt_departure    => '16.11.2018 17:45', +		sched_departure => '2018-11-16T17:36', +		rt_departure    => '2018-11-16T17:45',  		arr_station     => 'EG', -		sched_arrival   => '16.11.2018 18:34', -		rt_arrival      => '16.11.2018 19:00', +		sched_arrival   => '2018-11-16T18:34', +		rt_arrival      => '2018-11-16T19:00',  	}  );  $t->status_is(302)->header_is( location => '/journey/2' ); @@ -153,10 +153,10 @@ $t->post_ok(  		action          => 'save',  		train           => 'ICE 1',  		dep_station     => 'EE', -		sched_departure => '17.11.2018 15:42', +		sched_departure => '2018-11-17T15:42',  		rt_departure    => '',  		arr_station     => 'BL', -		sched_arrival   => '17.11.2018 19:42', +		sched_arrival   => '2018-11-17T19:42',  		rt_arrival      => '',  	}  ); diff --git a/t/12-journey-edit.t b/t/12-journey-edit.t index 5854d62..7a2d127 100644 --- a/t/12-journey-edit.t +++ b/t/12-journey-edit.t @@ -145,14 +145,10 @@ $t->post_ok(  	}  ); -$t->status_is(200) -  ->content_like(qr{M.nster\(Westf\)Hbf}) -  ->content_like(qr{Gelsenkirchen Hbf}) -  ->content_like(qr{RE 11238}) -  ->content_like(qr{Linie 42}) -  ->content_like(qr{16.10.2018 ..:36}) -  ->content_like(qr{16.10.2018 ..:34}) -  ->content_like(qr{Huhu}); +$t->status_is(200)->content_like(qr{M.nster\(Westf\)Hbf}) +  ->content_like(qr{Gelsenkirchen Hbf})->content_like(qr{RE 11238}) +  ->content_like(qr{Linie 42})->content_like(qr{2018-10-16T..:36}) +  ->content_like(qr{2018-10-16T..:34})->content_like(qr{Huhu});  $csrf_token = $t->tx->res->dom->at('input[name=csrf_token]')->attr('value'); @@ -163,10 +159,10 @@ $t->post_ok(  		csrf_token      => $csrf_token,  		from_name       => 'Münster(Westf)Hbf',  		to_name         => 'Gelsenkirchen Hbf', -		sched_departure => '16.10.2018 17:36', -		rt_departure    => '16.10.2018 17:36', -		sched_arrival   => '16.10.2018 18:34', -		rt_arrival      => '16.10.2018 18:34', +		sched_departure => '2018-10-16T17:36', +		rt_departure    => '2018-10-16T17:36', +		sched_arrival   => '2018-10-16T18:34', +		rt_arrival      => '2018-10-16T18:34',  	}  ); @@ -193,14 +189,10 @@ $t->post_ok(  	}  ); -$t->status_is(200) -  ->content_like(qr{M.nster\(Westf\)Hbf}) -  ->content_like(qr{Gelsenkirchen Hbf}) -  ->content_like(qr{RE 11238}) -  ->content_like(qr{Linie 42}) -  ->content_like(qr{16.10.2018 ..:36}) -  ->content_like(qr{16.10.2018 ..:34}) -  ->content_like(qr{Huhu}); +$t->status_is(200)->content_like(qr{M.nster\(Westf\)Hbf}) +  ->content_like(qr{Gelsenkirchen Hbf})->content_like(qr{RE 11238}) +  ->content_like(qr{Linie 42})->content_like(qr{2018-10-16T..:36}) +  ->content_like(qr{2018-10-16T..:34})->content_like(qr{Huhu});  $csrf_token = $t->tx->res->dom->at('input[name=csrf_token]')->attr('value'); @@ -211,10 +203,10 @@ $t->post_ok(  		csrf_token      => $csrf_token,  		from_name       => 'Münster(Westf)Hbf',  		to_name         => 'Gelsenkirchen Hbf', -		sched_departure => '16.10.2018 17:36', -		rt_departure    => '16.10.2018 17:42', -		sched_arrival   => '16.10.2018 18:34', -		rt_arrival      => '16.10.2018 18:33', +		sched_departure => '2018-10-16T17:36', +		rt_departure    => '2018-10-16T17:42', +		sched_arrival   => '2018-10-16T18:34', +		rt_arrival      => '2018-10-16T18:33',  	}  ); diff --git a/templates/add_intransit.html.ep b/templates/add_intransit.html.ep index 9d711c9..a044917 100644 --- a/templates/add_intransit.html.ep +++ b/templates/add_intransit.html.ep @@ -21,7 +21,7 @@  			<li>Eingabe der Fahrt als „Typ Linie Nummer“ oder „Typ Nummer“, z.B.  				„ICE 100“, „S 1 31133“ oder „ABR RE11 26720“</li>  			<li>Wenn Nummer nicht bekannt oder vorhanden: einen beliebigen Integer eintragen, z.B. „S 5X 0“ oder „U 11 0“</li>	 -			<li>Zeitangaben im Format DD.MM.YYYY HH:MM</li> +			<li>Zeitangaben im Format YYYY-MM-DDTHH:MM. Bei den Zwischenhalten kann auch nur HH:MM angegeben werden</li>  			<li>Das ausgewählte Backend bestimmt die verfügbaren Halte für Start, Ziel und Route. Siehe auch <a href="/static/stops.csv">stops.csv</a></li>  		</ul>  	</div> @@ -50,8 +50,8 @@  			<label for="dep_station">Start (Name oder ID)</label>  		</div>  		<div class="input-field col s12"> -			%= text_field 'sched_departure', id => 'sched_departure', class => 'validate', required => undef, pattern => '[0-9][0-9]?[.][0-9][0-9]?[.][0-9][0-9][0-9][0-9] +[0-9][0-9]:[0-9][0-9]' -			<label for="sched_departure">Geplante Abfahrt</label> +			%= datetime_field 'sched_departure', id => 'sched_departure', class => 'validate', required => undef +			<label for="sched_departure" class="active">Geplante Abfahrt</label>  		</div>  	</div>  	<div class="row"> @@ -60,8 +60,8 @@  			<label for="arr_station">Ziel (Name oder ID)</label>  		</div>  		<div class="input-field col s12"> -			%= text_field 'sched_arrival', id => 'sched_arrival', class => 'validate', required => undef, pattern => '[0-9][0-9]?[.][0-9][0-9]?[.][0-9][0-9][0-9][0-9] +[0-9][0-9]:[0-9][0-9]' -			<label for="sched_arrival">Geplante Ankunft</label> +			%= datetime_field 'sched_arrival', id => 'sched_arrival', class => 'validate', required => undef +			<label for="sched_arrival" class="active">Geplante Ankunft</label>  		</div>  	</div>  	<div class="row"> @@ -69,7 +69,7 @@  			%= text_area 'route', id => 'route', class => 'materialize-textarea'  			<label for="route">Halte (optional)</label><br/>  			Eine Station pro Zeile, wahlweise Unterwegshalte oder komplette Route<br/> -			Format: <i>Name</i> oder <i>Name</i> @ <i>Zeitpunkt</i> (inkl. Datum, siehe oben) +			Format: <i>Name</i> oder <i>Name</i> @ <i>Zeitpunkt</i> (Format siehe oben, ein ggf. ausgelassenes Datum wird ergänzt)  		</div>  	</div>  	<div class="row"> diff --git a/templates/add_journey.html.ep b/templates/add_journey.html.ep index cade37e..94f9270 100644 --- a/templates/add_journey.html.ep +++ b/templates/add_journey.html.ep @@ -33,7 +33,7 @@  			<li>Eingabe der Fahrt als „Typ Linie Nummer“ oder „Typ Nummer“, z.B.  				„ICE 100“, „S 1 31133“ oder „ABR RE11 26720“</li>  			<li>Wenn Nummer nicht bekannt oder vorhanden: einen beliebigen Integer eintragen, z.B. „S 5X 0“ oder „U 11 0“</li>	 -			<li>Zeitangaben im Format DD.MM.YYYY HH:MM</li> +			<li>Zeitangaben im Format YYYY-MM-DDTHH:MM</li>  			<li>Das ausgewählte Backend bestimmt die verfügbaren Halte für Start, Ziel und Route. Siehe auch <a href="/static/stops.csv">stops.csv</a></li>  		</ul>  	</div> @@ -69,12 +69,12 @@  			<label for="dep_station">Start (Name oder ID)</label>  		</div>  		<div class="input-field col s12"> -			%= text_field 'sched_departure', id => 'sched_departure', class => 'validate', required => undef, pattern => '[0-9][0-9]?[.][0-9][0-9]?[.][0-9][0-9][0-9][0-9] +[0-9][0-9]:[0-9][0-9]' -			<label for="sched_departure">Geplante Abfahrt</label> +			%= datetime_field 'sched_departure', id => 'sched_departure', class => 'validate', required => undef +			<label for="sched_departure" class="active">Geplante Abfahrt</label>  		</div>  		<div class="input-field col s12"> -			%= text_field 'rt_departure', id => 'rt_departure', class => 'validate', pattern => '[0-9][0-9]?[.][0-9][0-9]?[.][0-9][0-9][0-9][0-9] +[0-9][0-9]:[0-9][0-9]' -			<label for="rt_departure">Tatsächliche Abfahrt (wenn leer: pünktlich)</label> +			%= datetime_field 'rt_departure', id => 'rt_departure', class => 'validate' +			<label for="rt_departure" class="active">Tatsächliche Abfahrt (wenn leer: pünktlich)</label>  		</div>  	</div>  	<div class="row"> @@ -83,12 +83,12 @@  			<label for="arr_station">Ziel (Name oder ID)</label>  		</div>  		<div class="input-field col s12"> -			%= text_field 'sched_arrival', id => 'sched_arrival', class => 'validate', required => undef, pattern => '[0-9][0-9]?[.][0-9][0-9]?[.][0-9][0-9][0-9][0-9] +[0-9][0-9]:[0-9][0-9]' -			<label for="sched_arrival">Geplante Ankunft</label> +			%= datetime_field 'sched_arrival', id => 'sched_arrival', class => 'validate', required => undef +			<label for="sched_arrival" class="active">Geplante Ankunft</label>  		</div>  		<div class="input-field col s12"> -			%= text_field 'rt_arrival', id => 'rt_arrival', class => 'validate', pattern => '[0-9][0-9]?[.][0-9][0-9]?[.][0-9][0-9][0-9][0-9] +[0-9][0-9]:[0-9][0-9]' -			<label for="rt_arrival">Tatsächliche Ankunft (wenn leer: pünktlich)</label> +			%= datetime_field 'rt_arrival', id => 'rt_arrival', class => 'validate' +			<label for="rt_arrival" class="active">Tatsächliche Ankunft (wenn leer: pünktlich)</label>  		</div>  	</div>  	<div class="row"> diff --git a/templates/edit_journey.html.ep b/templates/edit_journey.html.ep index cb867e5..6316731 100644 --- a/templates/edit_journey.html.ep +++ b/templates/edit_journey.html.ep @@ -69,13 +69,13 @@  					<tr>  						<th scope="row">Geplante Abfahrt</th>  						<td class="input-field"> -							%= text_field 'sched_departure', id => 'sched_departure', class => 'validate', required => undef, pattern => '[0-9][0-9]?[.][0-9][0-9]?[.][0-9][0-9][0-9][0-9] +[0-9][0-9]:[0-9][0-9]' +							%= datetime_field 'sched_departure', id => 'sched_departure', class => 'validate', required => undef  						</td>  					</tr>  					<tr>  						<th scope="row">Tatsächliche Abfahrt</th>  						<td class="input-field"> -							%= text_field 'rt_departure', id => 'real_departure', class => 'validate', pattern => '[0-9][0-9]?[.][0-9][0-9]?[.][0-9][0-9][0-9][0-9] +[0-9][0-9]:[0-9][0-9]' +							%= datetime_field 'rt_departure', id => 'real_departure', class => 'validate'  						</td>  					</tr>  					<tr> @@ -87,13 +87,13 @@  					<tr>  						<th scope="row">Geplante Ankunft</th>  						<td class="input-field"> -							%= text_field 'sched_arrival', id => 'sched_arrival', class => 'validate', required => undef, pattern => '[0-9][0-9]?[.][0-9][0-9]?[.][0-9][0-9][0-9][0-9] +[0-9][0-9]:[0-9][0-9]' +							%= datetime_field 'sched_arrival', id => 'sched_arrival', class => 'validate', required => undef  						</td>  					</tr>  					<tr>  						<th scope="row">Tatsächliche Ankunft</th>  						<td class="input-field"> -							%= text_field 'rt_arrival', id => 'real_arrival', class => 'validate', pattern => '[0-9][0-9]?[.][0-9][0-9]?[.][0-9][0-9][0-9][0-9] +[0-9][0-9]:[0-9][0-9]' +							%= datetime_field 'rt_arrival', id => 'real_arrival', class => 'validate'  						</td>  					</tr>  					<tr> diff --git a/templates/history_by_month.html.ep b/templates/history_by_month.html.ep index c3b1004..dec4c8b 100644 --- a/templates/history_by_month.html.ep +++ b/templates/history_by_month.html.ep @@ -6,7 +6,7 @@  <div class="row">  	<div class="col s12 m12 l12 center-align"> -		<a href="/history/map?filter_from=<%= $filter_from->strftime('%d.%m.%Y') %>&filter_to=<%= $filter_to->strftime('%d.%m.%Y') %>" class="waves-effect waves-light btn"><i class="material-icons left" aria-hidden="true">map</i> Karte</a> +		<a href="/history/map?filter_from=<%= $filter_from->strftime('%F') %>&filter_to=<%= $filter_to->strftime('%F') %>" class="waves-effect waves-light btn"><i class="material-icons left" aria-hidden="true">map</i> Karte</a>  	</div>  </div> diff --git a/templates/history_by_year.html.ep b/templates/history_by_year.html.ep index 6aa0c2d..1557b77 100644 --- a/templates/history_by_year.html.ep +++ b/templates/history_by_year.html.ep @@ -7,7 +7,7 @@  <div class="row">  	% if (stash('have_review')) {  	<div class="col s12 m12 l5 center-align"> -		<a href="/history/map?filter_from=1.1.<%= $year %>&filter_to=31.12.<%= $year %>" class="waves-effect waves-light btn"><i class="material-icons left" aria-hidden="true">map</i> Karte</a> +		<a href="/history/map?filter_from=<%= $year %>-01-01&filter_to=<%= $year %>-12-31" class="waves-effect waves-light btn"><i class="material-icons left" aria-hidden="true">map</i> Karte</a>  	</div>  	<div class="col s12 m12 l2"> </div>  	<div class="col s12 m12 l5 center-align"> @@ -16,7 +16,7 @@  	% }  	% else {  	<div class="col s12 m12 l12 center-align"> -		<a href="/history/map?filter_from=1.1.<%= $year %>&filter_to=31.12.<%= $year %>" class="waves-effect waves-light btn"><i class="material-icons left" aria-hidden="true">map</i> Karte</a> +		<a href="/history/map?filter_from=<%= $year %>-01-01&filter_to=<%= $year %>-12-31" class="waves-effect waves-light btn"><i class="material-icons left" aria-hidden="true">map</i> Karte</a>  	</div>  	% }  </div> diff --git a/templates/history_map.html.ep b/templates/history_map.html.ep index c2ff9ed..6620cb2 100644 --- a/templates/history_map.html.ep +++ b/templates/history_map.html.ep @@ -88,14 +88,14 @@  	</p>  	<div class="row">  		<div class="input-field col s12"> -			%= text_field 'filter_from', id => 'filter_from', class => 'validate', pattern => '[0-9][0-9]?[.][0-9][0-9]?[.][0-9][0-9][0-9][0-9]( +[0-9][0-9]:[0-9][0-9])?' -			<label for="filter_from">Abfahrt ab (DD.MM.YYYY)</label> +			%= date_field 'filter_from', id => 'filter_from', class => 'validate' +			<label for="filter_from" class="active">Abfahrt ab</label>  		</div>  	</div>  	<div class="row">  		<div class="input-field col s12"> -			%= text_field 'filter_to', id => 'filter_to', class => 'validate', pattern => '[0-9][0-9]?[.][0-9][0-9]?[.][0-9][0-9][0-9][0-9]( +[0-9][0-9]:[0-9][0-9])?' -			<label for="filter_to">Abfahrt bis (DD.MM.YYYY)</label> +			%= date_field 'filter_to', id => 'filter_to', class => 'validate' +			<label for="filter_to" class="active">Abfahrt bis</label>  		</div>  	</div>  	<div class="row"> | 
