diff options
-rwxr-xr-x | lib/Travelynx.pm | 7 | ||||
-rwxr-xr-x | lib/Travelynx/Controller/Traveling.pm | 26 | ||||
-rw-r--r-- | share/locales/en_GB.po | 15 | ||||
-rw-r--r-- | templates/journey.html.ep | 79 | ||||
-rw-r--r-- | templates/polyline.gpx.ep | 20 |
5 files changed, 112 insertions, 35 deletions
diff --git a/lib/Travelynx.pm b/lib/Travelynx.pm index 607b153..586f1a0 100755 --- a/lib/Travelynx.pm +++ b/lib/Travelynx.pm @@ -69,6 +69,8 @@ sub startup { $self->types->type( csv => 'text/csv; charset=utf-8' ); $self->types->type( json => 'application/json; charset=utf-8' ); + $self->types->type( gpx => 'application/gpx+xml; charset=utf-8' ); + $self->types->type( xml => 'text/xml; charset=utf-8' ); $self->plugin('Config'); @@ -3174,6 +3176,11 @@ sub startup { $authed_r->get( '/journey/:id' => [ format => [ 'html', 'json' ] ] ) ->to( 'traveling#journey_details', format => undef ) ->name('journey'); + $authed_r->get( '/polyline/:id' => [ format => [ 'gpx', 'json' ] ] )->to( + 'traveling#journey_details', + format => undef, + polyline_export => 1 + )->name('polyline_download'); $authed_r->get('/s/*station')->to('traveling#station'); $authed_r->get('/confirm_mail/:token')->to('account#confirm_mail'); $authed_r->post('/account/privacy')->to('account#privacy'); diff --git a/lib/Travelynx/Controller/Traveling.pm b/lib/Travelynx/Controller/Traveling.pm index e23301e..084b45e 100755 --- a/lib/Travelynx/Controller/Traveling.pm +++ b/lib/Travelynx/Controller/Traveling.pm @@ -2149,6 +2149,32 @@ sub journey_details { ); if ($journey) { + + if ( $self->stash('polyline_export') ) { + delete $self->stash->{layout}; + my $xml = $self->render_to_string( + template => 'polyline', + name => sprintf( '%s %s: %s → %s', + $journey->{type}, $journey->{no}, + $journey->{from_name}, $journey->{to_name} ), + polyline => $journey->{polyline} + ); + $self->respond_to( + gpx => { + text => $xml, + format => 'gpx' + }, + json => { + json => [ + map { + $_->[2] ? [ $_->[0], $_->[1], int( $_->[2] ) ] : $_ + } @{ $journey->{polyline} } + ] + }, + ); + return; + } + my $map_data = $self->journeys_to_map_data( journeys => [$journey], include_manual => 1, diff --git a/share/locales/en_GB.po b/share/locales/en_GB.po index 6121045..48fb05a 100644 --- a/share/locales/en_GB.po +++ b/share/locales/en_GB.po @@ -270,6 +270,21 @@ msgstr "Export" msgid "journey.edit" msgstr "Edit" +msgid "journey.map-data" +msgstr "Map Data" + +msgid "journey.map.download" +msgstr "Download" + +msgid "journey.map.upload" +msgstr "Upload" + +msgid "journey.map.info" +msgstr "JSON format: [[lon, lat, station ID], ...], with lon/lat in WGS84 coordinates. GPX files are compatible with BRouter. Uploads may cover either the entire route or just the route segment that belongs to this checkin; station IDs are optional when uploading map data." + +msgid "journey.danger" +msgstr "Danger Zone" + msgid "journey.delete" msgstr "Delete" diff --git a/templates/journey.html.ep b/templates/journey.html.ep index f9c78ec..b7b4223 100644 --- a/templates/journey.html.ep +++ b/templates/journey.html.ep @@ -317,11 +317,24 @@ </div> </div> % if (not stash('readonly')) { - % if (stash('with_share')) { - <div class="row"> - <div class="col s12 m6 l6"> - </div> - <div class="col s12 m6 l6 center-align"> + <div class="row"> + <div class="col s12 m6 l4 center-align"> + <a class="btn waves-effect waves-light" href="<%= url_for('journey', id => $journey->{id}, format => 'json' ) %>"> + <i class="material-icons left" aria-hidden="true">file_download</i> + %= L('journey.export') + </a> + </div> + <div class="col s12 m6 l4 center-align"> + %= form_for '/journey/edit' => (method => 'POST') => begin + %= hidden_field 'journey_id' => param('journey_id') + <button class="btn waves-effect waves-light" type="submit" name="action" value="edit"> + <i class="material-icons left" aria-hidden="true">edit</i> + %= L('journey.edit') + </button> + %= end + </div> + <div class="col s12 m6 l4 center-align"> + % if (stash('with_share')) { <a class="btn waves-effect waves-light action-share" % if (stash('journey_visibility') eq 'public') { data-url="<%= url_for('public_journey', name => current_user()->{name}, id => $journey->{id} )->to_abs->scheme('https'); %>" @@ -334,50 +347,46 @@ <i class="material-icons left" aria-hidden="true">share</i> %= L('journey.share') </a> - </div> + % } </div> - % } + </div> + <h2><%= L('journey.map-data') %></h2> <div class="row"> - <div class="col s12 m6 l6"> + <div class="col s12 m6 l6 center-align"> + <a class="btn waves-effect waves-light" href="<%= url_for('polyline_download', id => $journey->{id}, format => 'json' ) %>"> + <i class="material-icons left" aria-label="<%= L('journey.map.download') %>">file_download</i> + JSON + </a> </div> <div class="col s12 m6 l6 center-align"> - <a class="btn waves-effect waves-light" href="<%= url_for('journey', id => $journey->{id}, format => 'json' ) %>"> - <i class="material-icons left" aria-hidden="true">file_download</i> - %= L('journey.export') + <a class="btn waves-effect waves-light" href="<%= url_for('polyline_download', id => $journey->{id}, format => 'gpx' ) %>"> + <i class="material-icons left" aria-label="<%= L('journey.map.download') %>">file_download</i> + GPX </a> </div> </div> - <div class="row hide-on-small-only"> + <div class="row"> <div class="col s12 m6 l6 center-align"> - <a class="waves-effect waves-light red btn action-delete" - data-id="<%= $journey->{id} %>" - data-checkin="<%= $journey->{checkin}->epoch %>" - data-checkout="<%= $journey->{checkout}->epoch %>"> - <i class="material-icons left">delete_forever</i> - %= L('journey.delete') + <a class="btn disabled waves-effect waves-light" href="<%= url_for('journey', id => $journey->{id}, format => 'json' ) %>"> + <i class="material-icons left" aria-label="<%= L('journey.map.upload') %>">file_upload</i> + JSON </a> </div> <div class="col s12 m6 l6 center-align"> - %= form_for '/journey/edit' => (method => 'POST') => begin - %= hidden_field 'journey_id' => param('journey_id') - <button class="btn waves-effect waves-light" type="submit" name="action" value="edit"> - <i class="material-icons left" aria-hidden="true">edit</i> - %= L('journey.edit') - </button> - %= end + <a class="btn disabled waves-effect waves-light" href="<%= url_for('journey', id => $journey->{id}, format => 'json' ) %>"> + <i class="material-icons left" aria-label="<%= L('journey.map.upload') %>">file_upload</i> + GPX + </a> </div> </div> - <div class="row hide-on-med-and-up"> - <div class="col s12 m6 l6 center-align"> - %= form_for '/journey/edit' => (method => 'POST') => begin - %= hidden_field 'journey_id' => param('journey_id') - <button class="btn waves-effect waves-light" type="submit" name="action" value="edit"> - <i class="material-icons left" aria-hidden="true">edit</i> - %= L('journey.edit') - </button> - %= end + <div class="row"> + <div class="col s12"> + %= L('journey.map.info') </div> - <div class="col s12 m6 l6 center-align" style="margin-top: 1em;"> + </div> + <h2><%= L('journey.danger') %></h2> + <div class="row"> + <div class="col s12 m12 l12 center-align" style="margin-top: 1em;"> <a class="waves-effect waves-light red btn action-delete" data-id="<%= $journey->{id} %>" data-checkin="<%= $journey->{checkin}->epoch %>" diff --git a/templates/polyline.gpx.ep b/templates/polyline.gpx.ep new file mode 100644 index 0000000..a243926 --- /dev/null +++ b/templates/polyline.gpx.ep @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<gpx + xmlns="http://www.topografix.com/GPX/1/1" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd" + version="1.1" + creator="travelynx <%= $version %>"> + <trk> + <name><%= $name %></name> + <trkseg> + % for my $entry (@{$polyline // []}) { + <trkpt lon="<%= $entry->[0] %>" lat="<%= $entry->[1] %>"> + % if ($entry->[2]) { + <name><%= $entry->[2] %></name> + % } + </trkpt> + % } + </trkseg> + </trk> +</gpx> |