diff options
-rw-r--r-- | .cypress/cypress/integration/around_filters.js | 4 | ||||
-rw-r--r-- | CHANGELOG.md | 2 | ||||
-rw-r--r-- | perllib/FixMyStreet/App.pm | 21 | ||||
-rw-r--r-- | perllib/FixMyStreet/Cobrand/Bristol.pm | 2 | ||||
-rw-r--r-- | perllib/FixMyStreet/Cobrand/Default.pm | 25 | ||||
-rw-r--r-- | perllib/FixMyStreet/Cobrand/Zurich.pm | 2 | ||||
-rw-r--r-- | perllib/FixMyStreet/Map/Google.pm | 1 | ||||
-rw-r--r-- | perllib/FixMyStreet/Map/OSM.pm | 1 | ||||
-rw-r--r-- | t/app/controller/around.t | 22 | ||||
-rw-r--r-- | t/app/controller/index.t | 6 | ||||
-rw-r--r-- | t/app/uri_for.t | 8 | ||||
-rw-r--r-- | t/map/google.t | 21 | ||||
-rw-r--r-- | templates/web/base/around/_error_multiple.html | 2 | ||||
-rw-r--r-- | templates/web/base/maps/google.html | 2 | ||||
-rw-r--r-- | templates/web/base/maps/openlayers.html | 2 | ||||
-rw-r--r-- | web/js/map-OpenLayers.js | 93 | ||||
-rw-r--r-- | web/js/map-OpenStreetMap.js | 2 | ||||
-rw-r--r-- | web/js/map-bing-ol.js | 2 | ||||
-rw-r--r-- | web/js/map-google-ol.js | 2 | ||||
-rw-r--r-- | web/js/map-streetview.js | 2 | ||||
-rw-r--r-- | web/js/map-toner-lite.js | 2 | ||||
-rw-r--r-- | web/js/map-wmts-bristol.js | 2 | ||||
-rw-r--r-- | web/js/map-wmts-zurich.js | 2 |
23 files changed, 109 insertions, 119 deletions
diff --git a/.cypress/cypress/integration/around_filters.js b/.cypress/cypress/integration/around_filters.js index d14fe34dd..7bd029856 100644 --- a/.cypress/cypress/integration/around_filters.js +++ b/.cypress/cypress/integration/around_filters.js @@ -19,7 +19,7 @@ describe('Around page filtering and push state', function() { cy.wait('@update-results'); cy.contains('1 to 6 of 6'); cy.contains('Street light not working'); - cy.url().should('include', 'status=closed%2Cfixed'); + cy.url().should('include', 'status=closed,fixed'); cy.get('#status_2').should('be.checked'); cy.go('back'); cy.wait('@update-results'); @@ -31,7 +31,7 @@ describe('Around page filtering and push state', function() { cy.wait('@update-results'); cy.contains('1 to 6 of 6'); cy.contains('Street light not working'); - cy.url().should('include', 'status=closed%2Cfixed'); + cy.url().should('include', 'status=closed,fixed'); cy.get('#status_2').should('be.checked'); }); diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b58e5cca..8f43c9558 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ ## Releases * Unreleased + - Front end improvements: + - Track map state in URL to make sharing links easier. #2242 - Admin improvements: - Include moderation history in report updates. #2379 - Allow moderation to potentially change state. #2381 diff --git a/perllib/FixMyStreet/App.pm b/perllib/FixMyStreet/App.pm index 051308920..21f9082bb 100644 --- a/perllib/FixMyStreet/App.pm +++ b/perllib/FixMyStreet/App.pm @@ -420,27 +420,6 @@ sub uri_with { return $uri; } -=head2 uri_for - - $uri = $c->uri_for( ... ); - -Like C<uri_for> except that it passes the uri to the cobrand to be altered if -needed. - -=cut - -sub uri_for { - my $c = shift; - my @args = @_; - - my $uri = $c->next::method(@args); - - my $cobranded_uri = $c->cobrand->uri($uri); - - # note that the returned uri may be a string not an object (eg cities) - return $cobranded_uri; -} - =head2 uri_for_email $uri = $c->uri_for_email( ... ); diff --git a/perllib/FixMyStreet/Cobrand/Bristol.pm b/perllib/FixMyStreet/Cobrand/Bristol.pm index 25dc5ab0a..0660acc79 100644 --- a/perllib/FixMyStreet/Cobrand/Bristol.pm +++ b/perllib/FixMyStreet/Cobrand/Bristol.pm @@ -23,8 +23,6 @@ sub map_type { 'Bristol'; } -sub default_link_zoom { 6 } - sub disambiguate_location { my $self = shift; my $string = shift; diff --git a/perllib/FixMyStreet/Cobrand/Default.pm b/perllib/FixMyStreet/Cobrand/Default.pm index 6c91da640..4c5d29ee5 100644 --- a/perllib/FixMyStreet/Cobrand/Default.pm +++ b/perllib/FixMyStreet/Cobrand/Default.pm @@ -397,25 +397,6 @@ Return cobrand extra data for the problem sub cobrand_data_for_generic_problem { '' } -=item uri - -Given a URL ($_[1]), QUERY, EXTRA_DATA, return a URL with any extra params -needed appended to it. - -In the default case, we need to make sure zoom is always present if lat/lon -are, to stop OpenLayers defaulting to null/0. - -=cut - -sub uri { - my ( $self, $uri ) = @_; - $uri->query_param( zoom => $self->default_link_zoom ) - if $uri->query_param('lat') && !$uri->query_param('zoom'); - - return $uri; -} - - =item header_params Return any params to be added to responses @@ -1002,18 +983,14 @@ sub tweak_all_reports_map {} sub can_support_problems { return 0; } -=item default_map_zoom / default_link_zoom +=item default_map_zoom default_map_zoom is used when displaying a map overriding the default of max-4 or max-3 depending on population density. -default_link_zoom is used in links that contain a 'lat' and no -zoom, to stop e.g. OpenLayers defaulting to null/0. - =cut sub default_map_zoom { undef }; -sub default_link_zoom { 3 } sub users_can_hide { return 0; } diff --git a/perllib/FixMyStreet/Cobrand/Zurich.pm b/perllib/FixMyStreet/Cobrand/Zurich.pm index 9d5ebc626..9b6a3b9cb 100644 --- a/perllib/FixMyStreet/Cobrand/Zurich.pm +++ b/perllib/FixMyStreet/Cobrand/Zurich.pm @@ -88,8 +88,6 @@ sub example_places { sub languages { [ 'de-ch,Deutsch,de_CH' ] } sub language_override { 'de-ch' } -sub default_link_zoom { 6 } - sub prettify_dt { my $self = shift; my $dt = shift; diff --git a/perllib/FixMyStreet/Map/Google.pm b/perllib/FixMyStreet/Map/Google.pm index f40eff167..c1fb05e43 100644 --- a/perllib/FixMyStreet/Map/Google.pm +++ b/perllib/FixMyStreet/Map/Google.pm @@ -44,6 +44,7 @@ sub display_map { if defined $c->get_param('lat'); $params{longitude} = Utils::truncate_coordinate($c->get_param('lon') + 0) if defined $c->get_param('lon'); + $params{zoomToBounds} = $params{any_zoom} && !defined $c->get_param('zoom'); my $zoom = defined $c->get_param('zoom') ? $c->get_param('zoom') + 0 : $default_zoom; $zoom = $numZoomLevels - 1 if $zoom >= $numZoomLevels; diff --git a/perllib/FixMyStreet/Map/OSM.pm b/perllib/FixMyStreet/Map/OSM.pm index a6a95b48b..a6cb6acea 100644 --- a/perllib/FixMyStreet/Map/OSM.pm +++ b/perllib/FixMyStreet/Map/OSM.pm @@ -57,6 +57,7 @@ sub display_map { if defined $c->get_param('lat'); $params{longitude} = Utils::truncate_coordinate($c->get_param('lon') + 0) if defined $c->get_param('lon'); + $params{zoomToBounds} = $params{any_zoom} && !defined $c->get_param('zoom'); my %data; $data{cobrand} = $c->cobrand; diff --git a/t/app/controller/around.t b/t/app/controller/around.t index cb36833ad..ed29d438c 100644 --- a/t/app/controller/around.t +++ b/t/app/controller/around.t @@ -18,28 +18,6 @@ subtest "check that if no query we get sent back to the homepage" => sub { is $mech->uri->path, '/', "redirected to '/'"; }; -# x,y requests were generated by the old map code. We keep the behavior for -# historic links -subtest "redirect x,y requests to lat/lon (301 - permanent)" => sub { - - FixMyStreet::override_config { - MAPIT_URL => 'http://mapit.uk/', - }, sub { - $mech->get_ok('/around?x=3281&y=1113'); - }; - - # did we redirect to lat,lon? - is $mech->uri->path, '/around', "still on /around"; - is_deeply { $mech->uri->query_form }, - { lat => 51.499825, lon => -0.140137, zoom => 3 }, - "lat,lon correctly set"; - - # was it a 301? - is $mech->res->code, 200, "got 200 for final destination"; - is $mech->res->previous->code, 301, "got 301 for redirect"; - -}; - # test various locations on inital search box foreach my $test ( { diff --git a/t/app/controller/index.t b/t/app/controller/index.t index 9be6dfa1e..bd268b3d7 100644 --- a/t/app/controller/index.t +++ b/t/app/controller/index.t @@ -29,15 +29,15 @@ subtest "does pc, (x,y), (e,n) or (lat,lon) go to /around" => sub { }, { in => { lat => 51.50100, lon => -0.14158 }, - out => { lat => 51.50100, lon => -0.14158, zoom => 3 }, + out => { lat => 51.50100, lon => -0.14158 }, }, { in => { x => 3281, y => 1113, }, - out => { lat => 51.499825, lon => -0.140137, zoom => 3 }, + out => { lat => 51.499825, lon => -0.140137 }, }, { in => { e => 1234, n => 4567 }, - out => { lat => 49.808509, lon => -7.544784, zoom => 3 }, + out => { lat => 49.808509, lon => -7.544784 }, }, ) { diff --git a/t/app/uri_for.t b/t/app/uri_for.t index 7d9c8dc07..61713f8b7 100644 --- a/t/app/uri_for.t +++ b/t/app/uri_for.t @@ -13,7 +13,6 @@ use URI; use_ok('FixMyStreet::App'); my $fms_c = ctx_request('http://www.fixmystreet.com/'); -my $fgm_c = ctx_request('http://www.fiksgatami.no/'); is( $fms_c->uri_for('/bar/baz') . "", @@ -33,11 +32,4 @@ is( 'URI with query' ); -# fiksgatami -is( - $fgm_c->uri_for( '/foo', { lat => 1.23, } ) . "", - 'http://www.fiksgatami.no/foo?lat=1.23&zoom=3', - 'FiksGataMi url with lat not zoom' -); - done_testing(); diff --git a/t/map/google.t b/t/map/google.t new file mode 100644 index 000000000..e2877f53c --- /dev/null +++ b/t/map/google.t @@ -0,0 +1,21 @@ +use FixMyStreet::Map::Google; +use FixMyStreet::Test; + +use Catalyst::Test 'FixMyStreet::App'; + +my $c = ctx_request('/'); + +FixMyStreet::Map::Google->display_map($c, any_zoom => 1); + +is_deeply $c->stash->{map}, { + any_zoom => 1, + zoomToBounds => 1, + type => 'google', + zoom => 15, + zoomOffset => 0, + numZoomLevels => 19, + zoom_act => 15, +}; + +done_testing(); + diff --git a/templates/web/base/around/_error_multiple.html b/templates/web/base/around/_error_multiple.html index 6a43eac32..34164973a 100644 --- a/templates/web/base/around/_error_multiple.html +++ b/templates/web/base/around/_error_multiple.html @@ -10,7 +10,7 @@ [% IF match.icon %] <img src="[% match.icon %]" alt=""> [% END %] - <a href="/around?latitude=[% match.latitude | uri %];longitude=[% match.longitude | uri %][% IF c.req.params.category %];category=[% c.req.params.category | uri %][% END %]">[% match.address | html %]</a> + <a href="/around?lat=[% match.latitude | uri %]&lon=[% match.longitude | uri %][% IF c.req.params.category %]&category=[% c.req.params.category | uri %][% END %]">[% match.address | html %]</a> </li> [% END %] </ul> diff --git a/templates/web/base/maps/google.html b/templates/web/base/maps/google.html index e8c07b113..eaa462c6c 100644 --- a/templates/web/base/maps/google.html +++ b/templates/web/base/maps/google.html @@ -14,7 +14,7 @@ $.extend(fixmystreet, { 'area': [ [% map.area.join(',') %] ], 'latitude': [% map.latitude %], 'longitude': [% map.longitude %], -[% IF map.any_zoom -%] +[% IF map.zoomToBounds -%] 'zoomToBounds': 1, [%- END %] [% IF map.zoom -%] diff --git a/templates/web/base/maps/openlayers.html b/templates/web/base/maps/openlayers.html index 524075371..2f748cb19 100644 --- a/templates/web/base/maps/openlayers.html +++ b/templates/web/base/maps/openlayers.html @@ -11,7 +11,7 @@ [%- END %] data-latitude=[% map.latitude %] data-longitude=[% map.longitude %] -[% IF map.any_zoom -%] +[% IF map.zoomToBounds -%] data-zoomToBounds=1 [%- END %] [% IF map.zoom -%] diff --git a/web/js/map-OpenLayers.js b/web/js/map-OpenLayers.js index 27e89df1d..a18741049 100644 --- a/web/js/map-OpenLayers.js +++ b/web/js/map-OpenLayers.js @@ -365,7 +365,7 @@ $.extend(fixmystreet.utils, { /* Make sure pins aren't going to reload just because we're zooming out, * we already have the pins when the page loaded */ function zoomToBounds(bounds) { - if (!bounds) { return; } + if (!bounds || !fixmystreet.markers.strategies) { return; } var strategy = fixmystreet.markers.strategies[0]; strategy.deactivate(); var center = bounds.getCenterLonLat(); @@ -466,6 +466,17 @@ $.extend(fixmystreet.utils, { return new_url; } + function update_history(qs, data) { + var new_url = update_url(qs); + history.pushState(data, null, new_url); + + // Ensure the permalink control is updated when the filters change + var permalink_controls = fixmystreet.map.getControlsByClass(/Permalink/); + if (permalink_controls.length) { + permalink_controls[0].updateLink(); + } + } + function page_changed_history() { if (!('pushState' in history)) { return; @@ -480,10 +491,9 @@ $.extend(fixmystreet.utils, { } else { delete qs.p; } - var new_url = update_url(qs); - history.pushState({ + update_history(new_url, { page_change: { 'page': page, 'show_old_reports': show_old_reports } - }, null, new_url); + }); } function categories_or_status_changed_history() { @@ -496,10 +506,9 @@ $.extend(fixmystreet.utils, { var sort_key = replace_query_parameter(qs, 'sort', 'sort'); var show_old_reports = replace_query_parameter(qs, 'show_old_reports', 'show_old_reports'); delete qs.p; - var new_url = update_url(qs); - history.pushState({ + update_history(qs, { filter_change: { 'filter_categories': filter_categories, 'statuses': filter_statuses, 'sort': sort_key, 'show_old_reports': show_old_reports } - }, null, new_url); + }); } function setup_inspector_marker_drag() { @@ -567,8 +576,10 @@ $.extend(fixmystreet.utils, { f.geometry = new_geometry; this.removeAllFeatures(); this.addFeatures([f]); - var qs = fixmystreet.utils.parse_query_string(); - if (!qs.bbox) { + // Look at original href here to know if location was present at load. + // If it was, we don't want to zoom out to the bounds of the area. + var qs = OpenLayers.Util.getParameters(fixmystreet.original.href); + if (!qs.bbox && !qs.lat && !qs.lon) { zoomToBounds(extent); } } else { @@ -820,15 +831,6 @@ $.extend(fixmystreet.utils, { fixmystreet.map.addLayer(layer); } - if (!fixmystreet.map.getCenter()) { - var centre = new OpenLayers.LonLat( fixmystreet.longitude, fixmystreet.latitude ); - centre.transform( - new OpenLayers.Projection("EPSG:4326"), - fixmystreet.map.getProjectionObject() - ); - fixmystreet.map.setCenter(centre, fixmystreet.zoom || 3); - } - // map.getCenter() returns a position in "map units", but sometimes you // want the center in GPS-style latitude/longitude coordinates (WGS84) // for example, to pass as GET params to fixmystreet.com/report/new. @@ -910,9 +912,34 @@ OpenLayers.Control.PanZoomFMS = OpenLayers.Class(OpenLayers.Control.PanZoom, { } }); +OpenLayers.Control.ArgParserFMS = OpenLayers.Class(OpenLayers.Control.ArgParser, { + getParameters: function(url) { + var args = OpenLayers.Control.ArgParser.prototype.getParameters.apply(this, arguments); + // Get defaults from provided data if not in URL + if (!args.lat && !args.lon) { + args.lon = fixmystreet.longitude; + args.lat = fixmystreet.latitude; + } + if (args.lat && !args.zoom) { + args.zoom = fixmystreet.zoom || 3; + } + return args; + }, + + CLASS_NAME: "OpenLayers.Control.ArgParserFMS" +}); + /* Overriding Permalink so that it can pass the correct zoom to OSM */ OpenLayers.Control.PermalinkFMS = OpenLayers.Class(OpenLayers.Control.Permalink, { _updateLink: function(alter_zoom) { + // this.base was originally set in initialize(), but the window's href + // may have changed since then if e.g. the map filters have been updated. + // NB this won't change the base of the 'problems nearby' permalink on + // /report, as this would result in it pointing at the wrong page. + if (this.base !== '/around' && fixmystreet.page !== 'report') { + this.base = window.location.href; + } + var separator = this.anchor ? '#' : '?'; var href = this.base; if (href.indexOf(separator) != -1) { @@ -925,7 +952,17 @@ OpenLayers.Control.PermalinkFMS = OpenLayers.Class(OpenLayers.Control.Permalink, if ( alter_zoom ) { zoom += fixmystreet.zoomOffset; } - href += separator + OpenLayers.Util.getParameterString(this.createParams(center, zoom)); + + var params = this.createParams(center, zoom); + + // Strip out the ugly OpenLayers layers state string + delete params.layers; + if (params.lat && params.lon) { + // No need for the postcode string either, if we have a latlon + delete params.pc; + } + + href += separator + OpenLayers.Util.getParameterString(params); // Could use mlat/mlon here as well if we are on a page with a marker if (this.base == '/around') { href += '&js=1'; @@ -937,15 +974,21 @@ OpenLayers.Control.PermalinkFMS = OpenLayers.Class(OpenLayers.Control.Permalink, else { this.element.href = href; } + + if ('replaceState' in history) { + if (fixmystreet.page.match(/around|reports/)) { + history.replaceState( + history.state, + null, + href + ); + } + } }, updateLink: function() { this._updateLink(0); - } -}); -OpenLayers.Control.PermalinkFMSz = OpenLayers.Class(OpenLayers.Control.PermalinkFMS, { - updateLink: function() { - this._updateLink(1); - } + }, + CLASS_NAME: "OpenLayers.Control.PermalinkFMS" }); OpenLayers.Strategy.FixMyStreet = OpenLayers.Class(OpenLayers.Strategy.BBOX, { diff --git a/web/js/map-OpenStreetMap.js b/web/js/map-OpenStreetMap.js index 4165f8ee4..52eb95493 100644 --- a/web/js/map-OpenStreetMap.js +++ b/web/js/map-OpenStreetMap.js @@ -4,7 +4,7 @@ fixmystreet.maps.config = function() { permalink_id = 'map_permalink'; } fixmystreet.controls = [ - new OpenLayers.Control.ArgParser(), + new OpenLayers.Control.ArgParserFMS(), new OpenLayers.Control.Attribution(), //new OpenLayers.Control.LayerSwitcher(), new OpenLayers.Control.Navigation(), diff --git a/web/js/map-bing-ol.js b/web/js/map-bing-ol.js index 526ad2da9..6c9ab8a62 100644 --- a/web/js/map-bing-ol.js +++ b/web/js/map-bing-ol.js @@ -6,7 +6,7 @@ fixmystreet.maps.config = function() { fixmystreet.controls = [ new OpenLayers.Control.Attribution(), - new OpenLayers.Control.ArgParser(), + new OpenLayers.Control.ArgParserFMS(), new OpenLayers.Control.Navigation(), new OpenLayers.Control.PermalinkFMS(permalink_id), new OpenLayers.Control.PanZoomFMS({id: 'fms_pan_zoom' }) diff --git a/web/js/map-google-ol.js b/web/js/map-google-ol.js index 99670d4f2..4b2d818c9 100644 --- a/web/js/map-google-ol.js +++ b/web/js/map-google-ol.js @@ -23,7 +23,7 @@ fixmystreet.maps.config = function() { } fixmystreet.controls = [ - new OpenLayers.Control.ArgParser(), + new OpenLayers.Control.ArgParserFMS(), new OpenLayers.Control.Navigation(), new OpenLayers.Control.PermalinkFMS(permalink_id), new OpenLayers.Control.PanZoomFMS({id: 'fms_pan_zoom' }) diff --git a/web/js/map-streetview.js b/web/js/map-streetview.js index 6d9195246..4701a7f20 100644 --- a/web/js/map-streetview.js +++ b/web/js/map-streetview.js @@ -1,6 +1,6 @@ fixmystreet.maps.config = function() { fixmystreet.controls = [ - new OpenLayers.Control.ArgParser(), + new OpenLayers.Control.ArgParserFMS(), new OpenLayers.Control.Navigation(), new OpenLayers.Control.Permalink(), new OpenLayers.Control.PanZoomFMS() diff --git a/web/js/map-toner-lite.js b/web/js/map-toner-lite.js index eda12ff28..0700dbb55 100644 --- a/web/js/map-toner-lite.js +++ b/web/js/map-toner-lite.js @@ -4,7 +4,7 @@ fixmystreet.maps.config = function() { permalink_id = 'map_permalink'; } fixmystreet.controls = [ - new OpenLayers.Control.ArgParser(), + new OpenLayers.Control.ArgParserFMS(), new OpenLayers.Control.Navigation(), new OpenLayers.Control.PermalinkFMS(permalink_id), new OpenLayers.Control.PanZoomFMS({id: 'fms_pan_zoom' }) diff --git a/web/js/map-wmts-bristol.js b/web/js/map-wmts-bristol.js index 35f5ed0d6..88db20c52 100644 --- a/web/js/map-wmts-bristol.js +++ b/web/js/map-wmts-bristol.js @@ -104,7 +104,7 @@ fixmystreet.maps.config = function() { } fixmystreet.controls = [ - new OpenLayers.Control.ArgParser(), + new OpenLayers.Control.ArgParserFMS(), new OpenLayers.Control.Navigation(), new OpenLayers.Control.PermalinkFMS(permalink_id) ]; diff --git a/web/js/map-wmts-zurich.js b/web/js/map-wmts-zurich.js index eda0fbf44..346e9b89a 100644 --- a/web/js/map-wmts-zurich.js +++ b/web/js/map-wmts-zurich.js @@ -135,7 +135,7 @@ fixmystreet.maps.config = function() { // This stuff is copied from js/map-bing-ol.js fixmystreet.controls = [ - new OpenLayers.Control.ArgParser(), + new OpenLayers.Control.ArgParserFMS(), new OpenLayers.Control.Navigation() ]; if ( fixmystreet.page != 'report' || !$('html').hasClass('mobile') ) { |