[% loc('Set to my current location') %]
--
cgit v1.2.3
From 8531ba29675c046d71f6e99e3ad2f6cd72a3c584 Mon Sep 17 00:00:00 2001
From: Matthew Somerville
Date: Fri, 25 Nov 2016 18:09:26 +0000
Subject: [UK] Include specific domain in user search.
This deals with a bootstrapping issue of adding new admin users that
haven't yet interacted with the system.
---
perllib/FixMyStreet/Cobrand/Oxfordshire.pm | 2 ++
perllib/FixMyStreet/Cobrand/UKCouncils.pm | 15 +++++++++++----
2 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/perllib/FixMyStreet/Cobrand/Oxfordshire.pm b/perllib/FixMyStreet/Cobrand/Oxfordshire.pm
index a476b5e9b..dca208e98 100644
--- a/perllib/FixMyStreet/Cobrand/Oxfordshire.pm
+++ b/perllib/FixMyStreet/Cobrand/Oxfordshire.pm
@@ -119,4 +119,6 @@ sub contact_email {
return join( '@', 'highway.enquiries', 'oxfordshire.gov.uk' );
}
+sub admin_user_domain { 'oxfordshire.gov.uk' }
+
1;
diff --git a/perllib/FixMyStreet/Cobrand/UKCouncils.pm b/perllib/FixMyStreet/Cobrand/UKCouncils.pm
index 42c9c5cbc..c22224307 100644
--- a/perllib/FixMyStreet/Cobrand/UKCouncils.pm
+++ b/perllib/FixMyStreet/Cobrand/UKCouncils.pm
@@ -55,8 +55,9 @@ sub updates_restriction {
sub users_restriction {
my ($self, $rs) = @_;
- # Council admins can only see users who are members of the same council or
- # users who have sent a report or update to that council.
+ # Council admins can only see users who are members of the same council,
+ # have an email address in a specified domain, or users who have sent a
+ # report or update to that council.
my $problem_user_ids = $self->problems->search(
undef,
@@ -73,10 +74,16 @@ sub users_restriction {
}
)->as_query;
- return $rs->search([
+ my $or_query = [
from_body => $self->council_id,
id => [ { -in => $problem_user_ids }, { -in => $update_user_ids } ],
- ]);
+ ];
+ if ($self->can('admin_user_domain')) {
+ my $domain = $self->admin_user_domain;
+ push @$or_query, email => { ilike => "%\@$domain" };
+ }
+
+ return $rs->search($or_query);
}
sub base_url {
--
cgit v1.2.3
From 82d08bb2a2b9f5c5ad594e65ad218e25050d62d7 Mon Sep 17 00:00:00 2001
From: Matthew Somerville
Date: Mon, 28 Nov 2016 14:18:50 +0000
Subject: Scroll to report inspect form if present.
---
web/cobrands/fixmystreet/fixmystreet.js | 3 +++
1 file changed, 3 insertions(+)
diff --git a/web/cobrands/fixmystreet/fixmystreet.js b/web/cobrands/fixmystreet/fixmystreet.js
index fed983a2c..b6fed1591 100644
--- a/web/cobrands/fixmystreet/fixmystreet.js
+++ b/web/cobrands/fixmystreet/fixmystreet.js
@@ -563,6 +563,9 @@ $.extend(fixmystreet.set_up, {
return;
}
+ // Focus on form
+ $('html,body').scrollTop($('#report_inspect_form').offset().top);
+
// On the manage/inspect report form, we already have all the extra inputs
// in the DOM, we just need to hide/show them as appropriate.
$('form#report_inspect_form [name=category]').change(function() {
--
cgit v1.2.3
From 6989e6d72e7e13f27c42fd4587294191e600a1a5 Mon Sep 17 00:00:00 2001
From: Matthew Somerville
Date: Fri, 25 Nov 2016 17:57:01 +0000
Subject: Always return arrayref from bodies_str_ids.
Prevents potential odd-element hash in e.g. response_priorities.
---
perllib/FixMyStreet/DB/Result/Problem.pm | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/perllib/FixMyStreet/DB/Result/Problem.pm b/perllib/FixMyStreet/DB/Result/Problem.pm
index f421394fa..ab6f20050 100644
--- a/perllib/FixMyStreet/DB/Result/Problem.pm
+++ b/perllib/FixMyStreet/DB/Result/Problem.pm
@@ -475,7 +475,7 @@ sub confirm {
sub bodies_str_ids {
my $self = shift;
- return unless $self->bodies_str;
+ return [] unless $self->bodies_str;
my @bodies = split( /,/, $self->bodies_str );
return \@bodies;
}
--
cgit v1.2.3
From bf3b3d271bd18ee25652a957d500e38f9c33237e Mon Sep 17 00:00:00 2001
From: Matthew Somerville
Date: Thu, 1 Dec 2016 13:03:35 +0000
Subject: Update problem lastupdate column on inspect save.
---
perllib/FixMyStreet/App/Controller/Report.pm | 1 +
1 file changed, 1 insertion(+)
diff --git a/perllib/FixMyStreet/App/Controller/Report.pm b/perllib/FixMyStreet/App/Controller/Report.pm
index 73479c584..13967601b 100644
--- a/perllib/FixMyStreet/App/Controller/Report.pm
+++ b/perllib/FixMyStreet/App/Controller/Report.pm
@@ -377,6 +377,7 @@ sub inspect : Private {
if ( $reputation_change != 0 ) {
$problem->user->update_reputation($reputation_change);
}
+ $problem->lastupdate( \'current_timestamp' );
$problem->update;
if ( defined($update_text) ) {
$problem->add_to_comments( {
--
cgit v1.2.3
From a503961c5acc60199df7e539d3dc3f537b2adbea Mon Sep 17 00:00:00 2001
From: Matthew Somerville
Date: Thu, 1 Dec 2016 13:06:24 +0000
Subject: Better path for showing config git version.
The default cobrand does not have a template directory, so the
directory change to it was not working. Use the root directory
of the repository instead.
---
perllib/FixMyStreet/App/Controller/Admin.pm | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/perllib/FixMyStreet/App/Controller/Admin.pm b/perllib/FixMyStreet/App/Controller/Admin.pm
index e91597bb0..3782063d5 100644
--- a/perllib/FixMyStreet/App/Controller/Admin.pm
+++ b/perllib/FixMyStreet/App/Controller/Admin.pm
@@ -129,7 +129,7 @@ sub index : Path : Args(0) {
sub config_page : Path( 'config' ) : Args(0) {
my ($self, $c) = @_;
- my $dir = $c->stash->{additional_template_paths}->[0];
+ my $dir = FixMyStreet->path_to();
my $git_version = `cd $dir && git describe --tags`;
chomp $git_version;
$c->stash(
--
cgit v1.2.3
From 7df5f6d00c34580987509a2ccb4520d2fde96866 Mon Sep 17 00:00:00 2001
From: Matthew Somerville
Date: Tue, 6 Dec 2016 11:58:50 +0000
Subject: [fixmystreet.com] Fix typo on /about/council.
---
templates/web/fixmystreet.com/about/council.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/templates/web/fixmystreet.com/about/council.html b/templates/web/fixmystreet.com/about/council.html
index 651e4f57f..6814f70c3 100644
--- a/templates/web/fixmystreet.com/about/council.html
+++ b/templates/web/fixmystreet.com/about/council.html
@@ -163,7 +163,7 @@
Starting from zero? Want a completely new system from beginning to end? Then opt for the full-service option.
-
Use FixMyStreet to manage reports every step of the way. This system handles from everything, from acknowledgement, through inspection to contractor instruction or resolution. Each element was co-designed with local government insiders who know exactly what’s needed for clear, simple highways parks and street case management.
+
Use FixMyStreet to manage reports every step of the way. This system handles everything, from acknowledgement, through inspection to contractor instruction or resolution. Each element was co-designed with local government insiders who know exactly what’s needed for clear, simple highways parks and street case management.
--
cgit v1.2.3
From 102418842a833c29f855557bf4c410290b5a2020 Mon Sep 17 00:00:00 2001
From: Dave Arter
Date: Tue, 6 Dec 2016 11:57:34 +0000
Subject: [Zurich] Fix 500 error when editing superusers
The Zurich::admin_type function was setting $c->stash->{body}, meaning that
when trying to edit a superuser the 'fetch_contacts' function wasn't being
called, causing an "Can't call method "all" on an undefined value" error as
$c->stash->{live_contacts} wasn't ever being set.
Fixed by changing the conditional to simply determine whether fetch_contacts
needs to be called.
Included a regression test that meant a small addition to the MapItZurich mock.
---
perllib/FixMyStreet/App/Controller/Admin.pm | 2 +-
t/Mock/MapItZurich.pm | 6 ++++++
t/cobrand/zurich.t | 15 ++++++++++++++-
3 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/perllib/FixMyStreet/App/Controller/Admin.pm b/perllib/FixMyStreet/App/Controller/Admin.pm
index 3782063d5..bbdf449aa 100644
--- a/perllib/FixMyStreet/App/Controller/Admin.pm
+++ b/perllib/FixMyStreet/App/Controller/Admin.pm
@@ -1377,7 +1377,7 @@ sub user_edit : Path('user_edit') : Args(1) {
}
if ( $user->from_body ) {
- unless ( $c->stash->{body} && $user->from_body->id eq $c->stash->{body}->id ) {
+ unless ( $c->stash->{live_contacts} ) {
$c->stash->{body} = $user->from_body;
$c->forward('fetch_contacts');
}
diff --git a/t/Mock/MapItZurich.pm b/t/Mock/MapItZurich.pm
index ece9a9b22..9195749f6 100644
--- a/t/Mock/MapItZurich.pm
+++ b/t/Mock/MapItZurich.pm
@@ -38,6 +38,12 @@ sub dispatch_request {
my $json = $self->json->encode({});
return [ 200, [ 'Content-Type' => 'application/json' ], [ $json ] ];
},
+
+ sub (GET + /area/*/children) {
+ my ($self, $area) = @_;
+ my $json = $self->json->encode({});
+ return [ 200, [ 'Content-Type' => 'application/json' ], [ $json ] ];
+ },
}
__PACKAGE__->run_if_script;
diff --git a/t/cobrand/zurich.t b/t/cobrand/zurich.t
index b59e546dd..ddaae1f90 100644
--- a/t/cobrand/zurich.t
+++ b/t/cobrand/zurich.t
@@ -102,8 +102,9 @@ sub get_export_rows_count {
my $EXISTING_REPORT_COUNT = 0;
+my $superuser;
subtest "set up superuser" => sub {
- my $superuser = $mech->log_in_ok( 'super@example.org' );
+ $superuser = $mech->log_in_ok( 'super@example.org' );
# a user from body $zurich is a superuser, as $zurich has no parent id!
$superuser->update({ from_body => $zurich->id });
$EXISTING_REPORT_COUNT = get_export_rows_count($mech);
@@ -968,6 +969,18 @@ subtest 'time_spent' => sub {
$mech->log_out_ok;
+FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ 'zurich' ],
+ MAPIT_URL => 'http://mapit.zurich/',
+ MAPIT_TYPES => [ 'ZZZ' ],
+}, sub {
+ LWP::Protocol::PSGI->register(t::Mock::MapItZurich->run_if_script, host => 'mapit.zurich');
+ subtest 'users at the top level can be edited' => sub {
+ $mech->log_in_ok( $superuser->email );
+ $mech->get_ok('/admin/user_edit/' . $superuser->id );
+ };
+};
+
END {
$mech->delete_body($subdivision);
$mech->delete_body($division);
--
cgit v1.2.3
From 7a78dc536468f8ed49b739ff69bd5e2ee26e64b0 Mon Sep 17 00:00:00 2001
From: Dave Arter
Date: Thu, 8 Dec 2016 13:29:24 +0000
Subject: [Oxfordshire] Update phone number on FAQ page
Fixes mysociety/fixmystreetforcouncils#133
---
templates/web/oxfordshire/about/faq-en-gb.html | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/templates/web/oxfordshire/about/faq-en-gb.html b/templates/web/oxfordshire/about/faq-en-gb.html
index b85943e0d..c88634e11 100755
--- a/templates/web/oxfordshire/about/faq-en-gb.html
+++ b/templates/web/oxfordshire/about/faq-en-gb.html
@@ -28,7 +28,7 @@
If you are reporting an emergency please do not report it online, but ring our
- Customer Service Centre on 0845 310 1111.
+ Customer Service Centre on 0345 310 1111.
- Please call us on 0845 310 1111 for urgent enquiries.
+ Please call us on 0345 310 1111 for urgent enquiries.
Potholes may need urgent attention if they are more than 40 millimetres in depth and/or
--
cgit v1.2.3
From 68ed4f77d2e7561351ded8113dffc27a6ce94800 Mon Sep 17 00:00:00 2001
From: Dave Arter
Date: Thu, 8 Dec 2016 13:45:23 +0000
Subject: Filter category should always carry through to form
When filtering the map by a category containing spaces, this category wasn't
being carried through to the dropdown on the new report form. Ensuring it's
wrapped in quotes in the jQuery selector fixes the problem.
Fixes mysociety/fixmystreetforcouncils#134
---
web/cobrands/fixmystreet/fixmystreet.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/web/cobrands/fixmystreet/fixmystreet.js b/web/cobrands/fixmystreet/fixmystreet.js
index b6fed1591..1701c5cd0 100644
--- a/web/cobrands/fixmystreet/fixmystreet.js
+++ b/web/cobrands/fixmystreet/fixmystreet.js
@@ -946,7 +946,7 @@ fixmystreet.update_pin = function(lonlat, savePushState) {
// something from it, then pre-fill the category field in the report,
// if it's a value already present in the drop-down.
var category = $("#filter_categories").val();
- if (category !== undefined && $("#form_category option[value="+category+"]").length) {
+ if (category !== undefined && $("#form_category option[value='"+category+"']").length) {
$("#form_category").val(category);
}
--
cgit v1.2.3
From e21a1886027956c45daed48edda7035719bcdf13 Mon Sep 17 00:00:00 2001
From: Matthew Somerville
Date: Fri, 9 Dec 2016 16:30:07 +0000
Subject: Manual OpenLayers patch for pointer event dragging
Thanks to Dave Tapuska and Chrome team:
https://bugs.chromium.org/p/chromium/issues/detail?id=670942
https://github.com/openlayers/ol2/issues/1510
---
web/js/OpenLayers/OpenLayers.fixmystreet.js | 4 ++--
web/js/OpenLayers/theme/default/style.css | 3 ++-
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/web/js/OpenLayers/OpenLayers.fixmystreet.js b/web/js/OpenLayers/OpenLayers.fixmystreet.js
index cfa4c2bee..df0a88c98 100644
--- a/web/js/OpenLayers/OpenLayers.fixmystreet.js
+++ b/web/js/OpenLayers/OpenLayers.fixmystreet.js
@@ -225,8 +225,8 @@ if(g)for(var h=0;!f&&hMath.floor(a.pageY)||0===a.pageX&&Math.floor(d)>Math.floor(a.pageX))d-=c,e-=b;else if(e
Date: Fri, 9 Dec 2016 16:50:03 +0000
Subject: Load OpenLayers stylesheet directly, not via JS.
This lets us version and cache-bust it as necessary, plus let
browser decide how to load it, we're always going to need it.
---
templates/web/base/common_header_tags.html | 2 ++
web/js/map-OpenLayers.js | 1 +
2 files changed, 3 insertions(+)
diff --git a/templates/web/base/common_header_tags.html b/templates/web/base/common_header_tags.html
index f34dea212..7c0ac4973 100644
--- a/templates/web/base/common_header_tags.html
+++ b/templates/web/base/common_header_tags.html
@@ -1,5 +1,7 @@
[% SET start = c.config.ADMIN_BASE_URL IF admin %]
+
+
diff --git a/web/js/map-OpenLayers.js b/web/js/map-OpenLayers.js
index 3de8e4d1f..a3cefa7da 100644
--- a/web/js/map-OpenLayers.js
+++ b/web/js/map-OpenLayers.js
@@ -606,6 +606,7 @@ var fixmystreet = fixmystreet || {};
// Create the basics of the map
fixmystreet.map = new OpenLayers.Map(
"map", OpenLayers.Util.extend({
+ theme: null,
controls: fixmystreet.controls,
displayProjection: new OpenLayers.Projection("EPSG:4326")
}, fixmystreet.map_options)
--
cgit v1.2.3
From 5d5d196ef1fdec2bb5c2d444da0126ecb5adeb78 Mon Sep 17 00:00:00 2001
From: Dave Arter
Date: Tue, 15 Nov 2016 15:14:25 +0000
Subject: =?UTF-8?q?Display=20nearby=20duplicate=20reports=20when=20setting?=
=?UTF-8?q?=20report=20category=20to=20=E2=80=98duplicate=E2=80=99?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
templates/web/base/report/_inspect.html | 5 +++++
web/cobrands/fixmystreet/fixmystreet.js | 34 +++++++++++++++++++++++++++++++++
2 files changed, 39 insertions(+)
diff --git a/templates/web/base/report/_inspect.html b/templates/web/base/report/_inspect.html
index 012411b7e..a09d75d40 100644
--- a/templates/web/base/report/_inspect.html
+++ b/templates/web/base/report/_inspect.html
@@ -76,6 +76,11 @@
[% END %]
+
+
+ Which report is it a duplicate of?
+
+
[% END %]
diff --git a/web/cobrands/fixmystreet/fixmystreet.js b/web/cobrands/fixmystreet/fixmystreet.js
index 1701c5cd0..a7e6f28f0 100644
--- a/web/cobrands/fixmystreet/fixmystreet.js
+++ b/web/cobrands/fixmystreet/fixmystreet.js
@@ -391,6 +391,40 @@ $.extend(fixmystreet.set_up, {
},
+ state_change: function() {
+ // Deal with changes to report state by inspector/other staff, specifically
+ // displaying nearby reports if it's changed to 'duplicate'.
+ $("#report_inspect_form").on("change.state", "select#state", function() {
+ var state = $(this).val();
+
+ if (state !== "duplicate") {
+ $("#js-duplicate-reports").addClass("hidden");
+ $("#js-duplicate-reports ul").empty();
+ return;
+ }
+
+ var args = {
+ state: state,
+ filter_category: $("#report_inspect_form select#category").val()
+ };
+ var bounds = fixmystreet.map.getExtent();
+ bounds.transform(bounds.transform(fixmystreet.map.getProjectionObject(), new OpenLayers.Projection("EPSG:4326")));
+ args.bbox = bounds.toBBOX();
+
+ args.latitude = $('input[name="latitude"]').val();
+ args.longitude = $('input[name="longitude"]').val();
+
+ console.log(args);
+
+ $.getJSON('/ajax', args, function(data) {
+ var $reports = $(data.current);
+ $("#js-duplicate-reports").removeClass("hidden");
+ $reports.slice(0, 5).appendTo($("#js-duplicate-reports ul").empty());
+ });
+ });
+ },
+
+
contribute_as: function() {
$('.content').on('change', '.js-contribute-as', function(){
var opt = this.options[this.selectedIndex],
--
cgit v1.2.3
From dc151edce28d2e5bf873f8e86473a82b9c6f178a Mon Sep 17 00:00:00 2001
From: Dave Arter
Date: Tue, 15 Nov 2016 17:08:57 +0000
Subject: Store and display selected duplicate report
---
perllib/FixMyStreet/App/Controller/Report.pm | 2 +-
perllib/FixMyStreet/DB/Result/Problem.pm | 11 +++++++++++
templates/web/base/report/_inspect.html | 11 ++++++++---
templates/web/base/report/_item.html | 2 +-
web/cobrands/fixmystreet/fixmystreet.js | 21 +++++++++++++++++----
web/cobrands/sass/_report_list_pins.scss | 8 ++++++++
6 files changed, 46 insertions(+), 9 deletions(-)
diff --git a/perllib/FixMyStreet/App/Controller/Report.pm b/perllib/FixMyStreet/App/Controller/Report.pm
index 13967601b..a9d171d33 100644
--- a/perllib/FixMyStreet/App/Controller/Report.pm
+++ b/perllib/FixMyStreet/App/Controller/Report.pm
@@ -320,7 +320,7 @@ sub inspect : Private {
my $reputation_change = 0;
if ($permissions->{report_inspect}) {
- foreach (qw/detailed_information traffic_information/) {
+ foreach (qw/detailed_information traffic_information duplicate_of/) {
$problem->set_extra_metadata( $_ => $c->get_param($_) );
}
diff --git a/perllib/FixMyStreet/DB/Result/Problem.pm b/perllib/FixMyStreet/DB/Result/Problem.pm
index ab6f20050..c63e6c881 100644
--- a/perllib/FixMyStreet/DB/Result/Problem.pm
+++ b/perllib/FixMyStreet/DB/Result/Problem.pm
@@ -1032,4 +1032,15 @@ has shortlisted_user => (
},
);
+has duplicate_of => (
+ is => 'ro',
+ lazy => 1,
+ default => sub {
+ my $self = shift;
+ my $duplicate_of = $self->get_extra_metadata("duplicate_of");
+ return unless defined $duplicate_of;
+ return $self->result_source->schema->resultset('Problem')->search({ id => $duplicate_of })->first;
+ },
+);
+
1;
diff --git a/templates/web/base/report/_inspect.html b/templates/web/base/report/_inspect.html
index a09d75d40..d5df3d42e 100644
--- a/templates/web/base/report/_inspect.html
+++ b/templates/web/base/report/_inspect.html
@@ -10,6 +10,7 @@
[% loc('Report ID:') %]
[% problem.id %]
+
[% SET local_coords = problem.local_coords; %]
@@ -76,10 +77,14 @@
[% END %]
-
-
+
+
Which report is it a duplicate of?
-
+
+ [% IF problem.duplicate_of %]
+ [% INCLUDE 'report/_item.html' no_fixed = 1 item_extra_class = 'item-list__item--with-pin item-list--reports__item--selected' problem = problem.duplicate_of %]
+ [% END %]
+
[% END %]
diff --git a/templates/web/base/report/_item.html b/templates/web/base/report/_item.html
index 5894c5d81..0f42b00ce 100644
--- a/templates/web/base/report/_item.html
+++ b/templates/web/base/report/_item.html
@@ -1,4 +1,4 @@
-
[% FOR duplicate IN problem.duplicates %]
[% INCLUDE 'report/_item.html' problem = duplicate %]
[% END %]
diff --git a/templates/web/base/report/display.html b/templates/web/base/report/display.html
index 1ee5c4636..7c26c4938 100644
--- a/templates/web/base/report/display.html
+++ b/templates/web/base/report/display.html
@@ -40,12 +40,19 @@
[% INCLUDE 'report/banner.html' %]
[% INCLUDE 'report/_main.html' %]
+
+[% IF problem.duplicate_of %]
+ [% INCLUDE 'report/duplicate-no-updates.html' hide_header = 1 %]
+[% END %]
+
[% TRY %][% INCLUDE 'report/_message_manager.html' %][% CATCH file %][% END %]
[% INCLUDE 'report/display_tools.html' %]
[% TRY %][% INCLUDE 'report/sharing.html' %][% CATCH file %][% END %]
[% INCLUDE 'report/updates.html' %]
-[% IF NOT shown_form %]
+[% IF problem.duplicate_of %]
+ [% INCLUDE 'report/duplicate-no-updates.html' %]
+[% ELSIF NOT shown_form %]
[% INCLUDE 'report/update-form.html' %]
[% END %]
diff --git a/templates/web/base/report/duplicate-no-updates.html b/templates/web/base/report/duplicate-no-updates.html
new file mode 100644
index 000000000..eb9ded728
--- /dev/null
+++ b/templates/web/base/report/duplicate-no-updates.html
@@ -0,0 +1,7 @@
+
+ [% UNLESS hide_header %]
[% loc( 'Provide an update') %]
[% END %]
+
[% loc("This report is a duplicate. Please leave updates on the original report:") %]
+
+ [% INCLUDE 'report/_item.html' item_extra_class = 'item-list__item--with-pin item-list--reports__item--selected' problem = problem.duplicate_of %]
+
+
diff --git a/templates/web/bromley/report/display.html b/templates/web/bromley/report/display.html
index 9f2089d28..4c1a69bca 100644
--- a/templates/web/bromley/report/display.html
+++ b/templates/web/bromley/report/display.html
@@ -21,147 +21,19 @@
[% INCLUDE 'report/banner.html' %]
[% INCLUDE 'report/_main.html' %]
-[% INCLUDE 'report/display_tools.html' %]
-[% INCLUDE 'report/updates.html' %]
-
-
-
[% loc( 'Provide an update') %]
-
- [% INCLUDE 'errors.html' %]
-
-
-
+[% INCLUDE 'report/display_tools.html' %]
+[% INCLUDE 'report/updates.html' %]
+[% IF problem.duplicate_of %]
+ [% INCLUDE 'report/duplicate-no-updates.html' %]
+[% ELSE %]
+ [% INCLUDE 'report/update-form.html' %]
+[% END %]
[% INCLUDE 'footer.html' %]
diff --git a/templates/web/bromley/report/update-form.html b/templates/web/bromley/report/update-form.html
new file mode 100644
index 000000000..112cb2960
--- /dev/null
+++ b/templates/web/bromley/report/update-form.html
@@ -0,0 +1,137 @@
+
+
[% loc( 'Provide an update') %]
+
+ [% INCLUDE 'errors.html' %]
+
+
+
--
cgit v1.2.3
From 05ba5147de9dc7b68f3c9048771fcabf80f20eca Mon Sep 17 00:00:00 2001
From: Dave Arter
Date: Thu, 24 Nov 2016 13:56:00 +0000
Subject: Display nearby candidate reports when marking as duplicate
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Use Problem->pin_data for single report page
- Promote markers_highlight to fixmystreet.maps API
We want to highlight map pins on the duplicate report selection UI, so let's use
what's already there instead of writing something new.
- Make sure duplicate report pins aren’t draggable
---
perllib/FixMyStreet/App/Controller/Report.pm | 20 ++++---
perllib/FixMyStreet/DB/Result/Problem.pm | 1 +
web/cobrands/fixmystreet/fixmystreet.js | 30 +++++++++-
web/js/map-OpenLayers.js | 86 ++++++++++++++++------------
web/js/map-google.js | 3 +
5 files changed, 94 insertions(+), 46 deletions(-)
diff --git a/perllib/FixMyStreet/App/Controller/Report.pm b/perllib/FixMyStreet/App/Controller/Report.pm
index f9eaf583c..154f0ac94 100644
--- a/perllib/FixMyStreet/App/Controller/Report.pm
+++ b/perllib/FixMyStreet/App/Controller/Report.pm
@@ -231,13 +231,8 @@ sub generate_map_tags : Private {
latitude => $problem->latitude,
longitude => $problem->longitude,
pins => $problem->used_map
- ? [ {
- latitude => $problem->latitude,
- longitude => $problem->longitude,
- colour => $c->cobrand->pin_colour($problem, 'report'),
- type => 'big',
- } ]
- : [],
+ ? [ $problem->pin_data($c, 'report', type => 'big') ]
+ : [],
);
return 1;
@@ -431,14 +426,21 @@ sub nearby_json : Private {
my $nearby = $c->model('DB::Nearby')->nearby(
$c, $dist, [ $p->id ], 5, $p->latitude, $p->longitude, undef, [ $p->category ], undef
);
- # my @reports = map { $_->problem : $_; } @$nearby;
+ my @pins = map {
+ my $p = $_->problem;
+ my $colour = $c->cobrand->pin_colour( $p, 'around' );
+ [ $p->latitude, $p->longitude,
+ $colour,
+ $p->id, $p->title_safe, 'small', JSON->false
+ ]
+ } @$nearby;
my $on_map_list_html = $c->render_fragment(
'around/on_map_list_items.html',
{ on_map => [], around_map => $nearby }
);
- my $json = {};
+ my $json = { pins => \@pins };
$json->{current} = $on_map_list_html if $on_map_list_html;
my $body = encode_json($json);
$c->res->content_type('application/json; charset=utf-8');
diff --git a/perllib/FixMyStreet/DB/Result/Problem.pm b/perllib/FixMyStreet/DB/Result/Problem.pm
index b7573d994..ec1534fe9 100644
--- a/perllib/FixMyStreet/DB/Result/Problem.pm
+++ b/perllib/FixMyStreet/DB/Result/Problem.pm
@@ -942,6 +942,7 @@ sub pin_data {
id => $self->id,
title => $opts{private} ? $self->title : $self->title_safe,
problem => $self,
+ type => $opts{type},
}
};
diff --git a/web/cobrands/fixmystreet/fixmystreet.js b/web/cobrands/fixmystreet/fixmystreet.js
index b314bc991..2a5c85872 100644
--- a/web/cobrands/fixmystreet/fixmystreet.js
+++ b/web/cobrands/fixmystreet/fixmystreet.js
@@ -402,7 +402,8 @@ $.extend(fixmystreet.set_up, {
longitude: $('input[name="longitude"]').val()
};
$("#js-duplicate-reports ul").html("
Loading...
");
- $.getJSON('/report/'+report_id+'/nearby', args, function(data) {
+ var nearby_url = '/report/'+report_id+'/nearby.json';
+ $.getJSON(nearby_url, args, function(data) {
var duplicate_of = $("#report_inspect_form [name=duplicate_of]").val();
var $reports = $(data.current)
.filter("li")
@@ -410,6 +411,16 @@ $.extend(fixmystreet.set_up, {
.slice(0, 5);
$reports.filter("[data-report-id="+duplicate_of+"]").addClass("item-list--reports__item--selected");
+ (function() {
+ var timeout;
+ $reports.on('mouseenter', function(){
+ clearTimeout(timeout);
+ fixmystreet.maps.markers_highlight(parseInt($(this).data('reportId'), 10));
+ }).on('mouseleave', function(){
+ timeout = setTimeout(fixmystreet.maps.markers_highlight, 50);
+ });
+ })();
+
$("#js-duplicate-reports ul").empty().prepend($reports);
$reports.find("a").click(function() {
@@ -419,9 +430,26 @@ $.extend(fixmystreet.set_up, {
$(this).closest("li").addClass("item-list--reports__item--selected");
return false;
});
+
+ show_nearby_pins(data, report_id);
});
}
+ function show_nearby_pins(data, report_id) {
+ var markers = fixmystreet.maps.markers_list( data.pins, true );
+ // We're replacing all the features in the markers layer with the
+ // possible duplicates, but the list of pins from the server doesn't
+ // include the current report. So we need to extract the feature for
+ // the current report and include it in the list of features we're
+ // showing on the layer.
+ var report_marker = fixmystreet.maps.get_marker_by_id(parseInt(report_id, 10));
+ if (report_marker) {
+ markers.unshift(report_marker);
+ }
+ fixmystreet.markers.removeAllFeatures();
+ fixmystreet.markers.addFeatures( markers );
+ }
+
function state_change() {
// The duplicate report list only makes sense when state is 'duplicate'
if ($(this).val() !== "duplicate") {
diff --git a/web/js/map-OpenLayers.js b/web/js/map-OpenLayers.js
index a3cefa7da..49801911b 100644
--- a/web/js/map-OpenLayers.js
+++ b/web/js/map-OpenLayers.js
@@ -90,7 +90,8 @@ var fixmystreet = fixmystreet || {};
size: pin[5] || marker_size,
faded: 0,
id: pin[3],
- title: pin[4] || ''
+ title: pin[4] || '',
+ draggable: pin[6] === false ? false : true
});
markers.push( marker );
}
@@ -144,7 +145,7 @@ var fixmystreet = fixmystreet || {};
admin_drag: function(pin_moved_callback, confirm_change) {
confirm_change = confirm_change || false;
var original_lonlat;
- var drag = new OpenLayers.Control.DragFeature( fixmystreet.markers, {
+ var drag = new OpenLayers.Control.DragFeatureFMS( fixmystreet.markers, {
onStart: function(feature, e) {
// Keep track of where the feature started, so we can put it
// back if the user cancels the operation.
@@ -167,12 +168,41 @@ var fixmystreet = fixmystreet || {};
} );
fixmystreet.map.addControl( drag );
drag.activate();
+ },
+
+ // `markers.redraw()` in markers_highlight will trigger an
+ // `overFeature` event if the mouse cursor is still over the same
+ // marker on the map, which would then run markers_highlight
+ // again, causing an infinite flicker while the cursor remains over
+ // the same marker. We really only want to redraw the markers when
+ // the cursor moves from one marker to another (ie: when there is an
+ // overFeature followed by an outFeature followed by an overFeature).
+ // Therefore, we keep track of the previous event in
+ // fixmystreet.latest_map_hover_event and only call markers_highlight
+ // if we know the previous event was different to the current one.
+ // (See the `overFeature` and `outFeature` callbacks inside of
+ // fixmystreet.select_feature).
+
+ markers_highlight: function(problem_id) {
+ for (var i = 0; i < fixmystreet.markers.features.length; i++) {
+ if (typeof problem_id == 'undefined') {
+ // There is no highlighted marker, so unfade this marker
+ fixmystreet.markers.features[i].attributes.faded = 0;
+ } else if (problem_id == fixmystreet.markers.features[i].attributes.id) {
+ // This is the highlighted marker, unfade it
+ fixmystreet.markers.features[i].attributes.faded = 0;
+ } else {
+ // This is not the hightlighted marker, fade it
+ fixmystreet.markers.features[i].attributes.faded = 1;
+ }
+ }
+ fixmystreet.markers.redraw();
}
};
var drag = {
activate: function() {
- this._drag = new OpenLayers.Control.DragFeature( fixmystreet.markers, {
+ this._drag = new OpenLayers.Control.DragFeatureFMS( fixmystreet.markers, {
onComplete: function(feature, e) {
fixmystreet.update_pin( feature.geometry );
}
@@ -195,35 +225,6 @@ var fixmystreet = fixmystreet || {};
fixmystreet.map.setCenter(center, z);
}
- // `markers.redraw()` in markers_highlight will trigger an
- // `overFeature` event if the mouse cursor is still over the same
- // marker on the map, which would then run markers_highlight
- // again, causing an infinite flicker while the cursor remains over
- // the same marker. We really only want to redraw the markers when
- // the cursor moves from one marker to another (ie: when there is an
- // overFeature followed by an outFeature followed by an overFeature).
- // Therefore, we keep track of the previous event in
- // fixmystreet.latest_map_hover_event and only call markers_highlight
- // if we know the previous event was different to the current one.
- // (See the `overFeature` and `outFeature` callbacks inside of
- // fixmystreet.select_feature).
-
- function markers_highlight(problem_id) {
- for (var i = 0; i < fixmystreet.markers.features.length; i++) {
- if (typeof problem_id == 'undefined') {
- // There is no highlighted marker, so unfade this marker
- fixmystreet.markers.features[i].attributes.faded = 0;
- } else if (problem_id == fixmystreet.markers.features[i].attributes.id) {
- // This is the highlighted marker, unfade it
- fixmystreet.markers.features[i].attributes.faded = 0;
- } else {
- // This is not the hightlighted marker, fade it
- fixmystreet.markers.features[i].attributes.faded = 1;
- }
- }
- fixmystreet.markers.redraw();
- }
-
function sidebar_highlight(problem_id) {
if (typeof problem_id !== 'undefined') {
var $a = $('.item-list--reports a[href$="/' + problem_id + '"]');
@@ -505,7 +506,7 @@ var fixmystreet = fixmystreet || {};
overFeature: function (feature) {
if (fixmystreet.latest_map_hover_event != 'overFeature') {
document.getElementById('map').style.cursor = 'pointer';
- markers_highlight(feature.attributes.id);
+ fixmystreet.maps.markers_highlight(feature.attributes.id);
sidebar_highlight(feature.attributes.id);
fixmystreet.latest_map_hover_event = 'overFeature';
}
@@ -513,7 +514,7 @@ var fixmystreet = fixmystreet || {};
outFeature: function (feature) {
if (fixmystreet.latest_map_hover_event != 'outFeature') {
document.getElementById('map').style.cursor = '';
- markers_highlight();
+ fixmystreet.maps.markers_highlight();
sidebar_highlight();
fixmystreet.latest_map_hover_event = 'outFeature';
}
@@ -666,9 +667,9 @@ var fixmystreet = fixmystreet || {};
var href = $('a', this).attr('href');
var id = parseInt(href.replace(/^.*[/]([0-9]+)$/, '$1'));
clearTimeout(timeout);
- markers_highlight(id);
+ fixmystreet.maps.markers_highlight(id);
}).on('mouseleave', '.item-list--reports__item', function(){
- timeout = setTimeout(markers_highlight, 50);
+ timeout = setTimeout(fixmystreet.maps.markers_highlight, 50);
});
})();
});
@@ -888,6 +889,19 @@ OpenLayers.Control.Click = OpenLayers.Class(OpenLayers.Control, {
}
});
+/* Drag handler that allows individual features to disable dragging */
+OpenLayers.Control.DragFeatureFMS = OpenLayers.Class(OpenLayers.Control.DragFeature, {
+ CLASS_NAME: "OpenLayers.Control.DragFeatureFMS",
+
+ overFeature: function(feature) {
+ if (feature.attributes.draggable) {
+ return OpenLayers.Control.DragFeature.prototype.overFeature.call(this, feature);
+ } else {
+ return false;
+ }
+ }
+})
+
OpenLayers.Renderer.SVGBig = OpenLayers.Class(OpenLayers.Renderer.SVG, {
MAX_PIXEL: 15E7,
CLASS_NAME: "OpenLayers.Renderer.SVGBig"
diff --git a/web/js/map-google.js b/web/js/map-google.js
index 4c3f6188e..be2df8502 100644
--- a/web/js/map-google.js
+++ b/web/js/map-google.js
@@ -56,6 +56,9 @@ fixmystreet.maps = {};
google.maps.event.trigger(fixmystreet.map, 'idle');
};
+ // This is a noop on Google Maps right now.
+ fixmystreet.maps.markers_highlight = function() {};
+
function PaddingControl(div) {
div.style.padding = '40px';
}
--
cgit v1.2.3
From ec6389940afce877a0bc7771d11a27ee7183f96a Mon Sep 17 00:00:00 2001
From: Dave Arter
Date: Tue, 22 Nov 2016 13:04:25 +0000
Subject: Make it clearer that report is closed when marked as duplicate
- Record state change when leaving update and marking as duplicate
- Change save button wording to match problem state when inspecting
- Make it clearer that updates marking a report as duplicate actually close the report
---
perllib/FixMyStreet/App/Controller/Report.pm | 7 +++++
t/app/controller/report_display.t | 2 +-
t/app/controller/report_inspect.t | 46 +++++++++++++++++++++++-----
t/app/controller/report_updates.t | 2 ++
templates/web/base/report/_inspect.html | 2 +-
templates/web/base/report/updates.html | 2 +-
web/cobrands/fixmystreet/fixmystreet.js | 13 +++++++-
7 files changed, 63 insertions(+), 11 deletions(-)
diff --git a/perllib/FixMyStreet/App/Controller/Report.pm b/perllib/FixMyStreet/App/Controller/Report.pm
index 154f0ac94..f7ccddc70 100644
--- a/perllib/FixMyStreet/App/Controller/Report.pm
+++ b/perllib/FixMyStreet/App/Controller/Report.pm
@@ -314,6 +314,7 @@ sub inspect : Private {
my $valid = 1;
my $update_text;
my $reputation_change = 0;
+ my %update_params = ();
if ($permissions->{report_inspect}) {
foreach (qw/detailed_information traffic_information duplicate_of/) {
@@ -341,6 +342,11 @@ sub inspect : Private {
if ( $problem->state eq 'hidden' ) {
$problem->get_photoset->delete_cached;
}
+ if ( $problem->state eq 'duplicate' && $old_state ne 'duplicate' ) {
+ # If the report is being closed as duplicate, make sure the
+ # update records this.
+ $update_params{problem_state} = "duplicate";
+ }
if ( $problem->state ne 'duplicate' ) {
$problem->unset_extra_metadata('duplicate_of');
}
@@ -388,6 +394,7 @@ sub inspect : Private {
state => 'confirmed',
mark_fixed => 0,
anonymous => 0,
+ %update_params,
} );
}
# This problem might no longer be visible on the current cobrand,
diff --git a/t/app/controller/report_display.t b/t/app/controller/report_display.t
index 9817a640d..fad8b2bbb 100644
--- a/t/app/controller/report_display.t
+++ b/t/app/controller/report_display.t
@@ -117,7 +117,7 @@ subtest "duplicate reports are signposted correctly" => sub {
my $report2_id = $report2->id;
ok $mech->get("/report/$report2_id"), "get '/report/$report2_id'";
- $mech->content_contains('This report is a duplicate.');
+ $mech->content_contains('This report is a duplicate');
$mech->content_contains($report->title);
$mech->log_out_ok;
diff --git a/t/app/controller/report_inspect.t b/t/app/controller/report_inspect.t
index b4d6636b9..56e6e957f 100644
--- a/t/app/controller/report_inspect.t
+++ b/t/app/controller/report_inspect.t
@@ -21,12 +21,14 @@ my $wodc = $mech->create_body_ok(2420, 'West Oxfordshire District Council', id =
$mech->create_contact_ok( body_id => $wodc->id, category => 'Horses', email => 'horses@example.net' );
-my ($report) = $mech->create_problems_for_body(1, $oxon->id, 'Test', {
+my ($report, $report2) = $mech->create_problems_for_body(2, $oxon->id, 'Test', {
category => 'Cows', cobrand => 'fixmystreet', areas => ',2237,2420',
whensent => \'current_timestamp',
latitude => 51.847693, longitude => -1.355908,
});
my $report_id = $report->id;
+my $report2_id = $report2->id;
+
my $user = $mech->log_in_ok('test@example.com');
$user->update( { from_body => $oxon } );
@@ -94,11 +96,6 @@ FixMyStreet::override_config {
};
subtest "test duplicate reports are shown" => sub {
- my ($report2) = $mech->create_problems_for_body(1, $oxon->id, 'The other report is a duplicate of this one', {
- category => $report->category, cobrand => 'fixmystreet', areas => ',2237,2420',
- whensent => \'current_timestamp',
- latitude => 51.847694, longitude => -1.355909,
- });
my $old_state = $report->state;
$report->set_extra_metadata('duplicate_of' => $report2->id);
$report->state('duplicate');
@@ -107,7 +104,6 @@ FixMyStreet::override_config {
$mech->get_ok("/report/$report_id");
$mech->content_contains($report2->title);
- my $report2_id = $report2->id;
$mech->get_ok("/report/$report2_id");
$mech->content_contains($report->title);
@@ -116,6 +112,42 @@ FixMyStreet::override_config {
$report->update;
};
+ subtest "marking a report as a duplicate with update correctly sets update status" => sub {
+ my $old_state = $report->state;
+ $report->comments->delete_all;
+
+ $mech->get_ok("/report/$report_id");
+ $mech->submit_form_ok({ button => 'save', with_fields => { state => 'Duplicate', duplicate_of => $report2->id, public_update => "This is a duplicate.", save_inspected => "1" } });
+ $report->discard_changes;
+
+ is $report->state, 'duplicate', 'report marked as duplicate';
+ is $report->comments->search({ problem_state => 'duplicate' })->count, 1, 'update marking report as duplicate was left';
+
+ $report->update({ state => $old_state });
+ };
+
+ subtest "marking a report as a duplicate doesn't clobber user-provided update" => sub {
+ my $old_state = $report->state;
+ $report->comments->delete_all;
+
+ $mech->get_ok("/report/$report_id");
+ my $update_text = "This text was entered as an update by the user.";
+ $mech->submit_form_ok({ button => 'save', with_fields => {
+ state => 'Duplicate',
+ duplicate_of => $report2->id,
+ public_update => $update_text,
+ save_inspected => "1",
+ }});
+ $report->discard_changes;
+
+ is $report->state, 'duplicate', 'report marked as duplicate';
+ is $report->comments->search({ problem_state => 'duplicate' })->count, 1, 'update marked report as duplicate';
+ $mech->content_contains($update_text);
+ $mech->content_lacks("Thank you for your report. This problem has already been reported.");
+
+ $report->update({ state => $old_state });
+ };
+
foreach my $test (
{ type => 'report_edit_priority', priority => 1 },
{ type => 'report_edit_category', category => 1 },
diff --git a/t/app/controller/report_updates.t b/t/app/controller/report_updates.t
index e1cd0da71..5a88097fa 100644
--- a/t/app/controller/report_updates.t
+++ b/t/app/controller/report_updates.t
@@ -685,6 +685,8 @@ for my $test (
my $meta_state = $test->{meta} || $test->{fields}->{state};
if ( $test->{reopened} ) {
like $update_meta->[0], qr/reopened$/, 'update meta says reopened';
+ } elsif ( $test->{state} eq 'duplicate' ) {
+ like $update_meta->[0], qr/closed as $meta_state$/, 'update meta includes state change';
} else {
like $update_meta->[0], qr/marked as $meta_state$/, 'update meta includes state change';
}
diff --git a/templates/web/base/report/_inspect.html b/templates/web/base/report/_inspect.html
index 6f49f3ecb..ccaa756c5 100644
--- a/templates/web/base/report/_inspect.html
+++ b/templates/web/base/report/_inspect.html
@@ -158,7 +158,7 @@