diff options
author | Chris Mytton <chrism@mysociety.org> | 2020-05-15 17:42:06 +0100 |
---|---|---|
committer | M Somerville <matthew-github@dracos.co.uk> | 2020-10-12 13:38:03 +0100 |
commit | 19deaf332d2843e3b4337f3e2047bce47e4a7cd1 (patch) | |
tree | 0b8c09257b286eda03f188f61e76acb2aeec9439 | |
parent | c778cff750282e814820b2f8ffee5e5c909e269a (diff) |
[Oxfordshire] Add instruct defect functionality back in
In the past Oxfordshire had a way for inspectors to "instruct a defect",
which generated a CSV which got emailed to Oxfordshire with a list of
defects.
They now want to bring this functionality back, but instead of emailing
a CSV they want it to call an API.
As a first step towards that goal, this change adds back some of the
instruct defect functionality that was removed in 68e18ff.
-rw-r--r-- | .cypress/cypress/integration/oxfordshire.js | 25 | ||||
-rwxr-xr-x | bin/browser-tests | 16 | ||||
-rwxr-xr-x | bin/fixmystreet.com/fixture | 3 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Report.pm | 10 | ||||
-rw-r--r-- | t/app/controller/report_inspect.t | 37 | ||||
-rw-r--r-- | templates/web/base/report/_inspect.html | 3 | ||||
-rw-r--r-- | templates/web/oxfordshire/report/inspect/_inspected.html | 7 | ||||
-rw-r--r-- | templates/web/oxfordshire/report/inspect/_raise_defect.html | 11 | ||||
-rw-r--r-- | web/cobrands/fixmystreet/staff.js | 13 |
9 files changed, 121 insertions, 4 deletions
diff --git a/.cypress/cypress/integration/oxfordshire.js b/.cypress/cypress/integration/oxfordshire.js new file mode 100644 index 000000000..f235802e6 --- /dev/null +++ b/.cypress/cypress/integration/oxfordshire.js @@ -0,0 +1,25 @@ +describe("Oxfordshire cobrand", function() { + it("allows inspectors to instruct defects", function() { + cy.server(); + cy.request({ + method: 'POST', + url: 'http://oxfordshire.localhost:3001/auth', + form: true, + body: { username: 'inspector-instructor@example.org', password_sign_in: 'password' } + }); + cy.visit('http://oxfordshire.localhost:3001/report/1'); + cy.contains('Oxfordshire'); + + cy.get('#report_inspect_form').should('be.visible'); + cy.get('#js-inspect-action-scheduled').should('not.be.visible'); + cy.get('#raise_defect_yes').should('not.have.attr', 'required'); + + cy.get('#report_inspect_form select[name=state]').select('Action scheduled'); + cy.get('#js-inspect-action-scheduled').should('be.visible'); + cy.get('#raise_defect_yes').should('have.attr', 'required', 'required'); + + cy.get('#report_inspect_form select[name=state]').select('No further action'); + cy.get('#js-inspect-action-scheduled').should('not.be.visible'); + cy.get('#raise_defect_yes').should('not.have.attr', 'required'); + }); +}); diff --git a/bin/browser-tests b/bin/browser-tests index e0b9bedfe..bfbe4e51d 100755 --- a/bin/browser-tests +++ b/bin/browser-tests @@ -11,7 +11,19 @@ my ($cobrand, $coords, $area_id, $name, $mapit_url, $coverage); BEGIN { $config_file = 'conf/general.yml-example'; - $cobrand = [ 'borsetshire', 'fixmystreet', 'northamptonshire', 'bathnes', 'buckinghamshire', 'hounslow', 'isleofwight', 'peterborough', 'tfl', 'hackney' ]; + $cobrand = [qw( + bathnes + borsetshire + buckinghamshire + fixmystreet + hackney + hounslow + isleofwight + northamptonshire + oxfordshire + peterborough + tfl + )]; $coords = '51.532851,-2.284277'; $area_id = 2608; $name = 'Borsetshire'; @@ -190,7 +202,7 @@ browser-tests [running options] [fixture options] [cypress options] --help this help message Fixture option: - --cobrand Cobrand(s) to use, default is fixmystreet,northamptonshire,bathnes,buckinghamshire,isleofwight,peterborough,tfl,hackney + --cobrand Cobrand(s) to use, default is fixmystreet,northamptonshire,bathnes,buckinghamshire,isleofwight,peterborough,tfl,hackney,oxfordshire --coords Default co-ordinates for created reports --area_id Area ID to use for created body --name Name to use for created body diff --git a/bin/fixmystreet.com/fixture b/bin/fixmystreet.com/fixture index e8dd3f364..59de8e222 100755 --- a/bin/fixmystreet.com/fixture +++ b/bin/fixmystreet.com/fixture @@ -103,6 +103,7 @@ if ($opt->test_fixtures) { { area_id => 2636, categories => [ 'Potholes', 'Private', 'Extra' ], name => 'Isle of Wight Council' }, { area_id => 2566, categories => [ 'Fallen branch', 'Light Out', 'Light Dim', 'Fallen Tree', 'Damaged Tree' ], name => 'Peterborough City Council' }, { area_id => 2498, categories => [ 'Incorrect timetable', 'Glass broken', 'Mobile Crane Operation' ], name => 'TfL' }, + { area_id => 2237, categories => [ 'Flytipping', 'Roads', 'Parks' ], name => 'Oxfordshire County Council' }, ) { $bodies->{$_->{area_id}} = FixMyStreet::DB::Factory::Body->find_or_create($_); my $cats = join(', ', @{$_->{categories}}); @@ -279,6 +280,7 @@ $priority->add_to_contacts($body->contacts->first); say "Created users, all with password 'password':"; my %users; my $perms_inspector = ['report_inspect', 'planned_reports']; +my $perms_inspector_with_instruct = [@$perms_inspector, 'report_instruct']; my $perms_cs = [ 'contribute_as_body', 'contribute_as_another_user', 'moderate', 'view_body_contribute_details', @@ -290,6 +292,7 @@ my $perms_cs_full = [ ]; foreach ( { name => 'Inspector Gadget', email => 'inspector@example.org', email_verified => 1, body => $body, permissions => $perms_inspector }, + { name => 'Inspector Instructor', email => 'inspector-instructor@example.org', email_verified => 1, body => $body, permissions => $perms_inspector_with_instruct }, { name => 'Harriet Helpful', email_verified => 1, email => 'cs@example.org', body => $body, permissions => $perms_cs }, { name => 'Andrew Agreeable', email_verified => 1, email => 'cs_full@example.org', body => $body, permissions => $perms_cs_full }, { name => 'Super User', email_verified => 1, email => 'super@example.org', body => $body, permissions => [ diff --git a/perllib/FixMyStreet/App/Controller/Report.pm b/perllib/FixMyStreet/App/Controller/Report.pm index 98c4aba17..1e5751588 100644 --- a/perllib/FixMyStreet/App/Controller/Report.pm +++ b/perllib/FixMyStreet/App/Controller/Report.pm @@ -467,7 +467,7 @@ sub inspect : Private { } } - if ( $c->get_param('include_update') ) { + if ( $c->get_param('include_update') or $c->get_param('raise_defect') ) { $update_text = Utils::cleanup_text( $c->get_param('public_update'), { allow_multiline => 1 } ); if (!$update_text) { $valid = 0; @@ -512,6 +512,14 @@ sub inspect : Private { }; $c->user->create_alert($problem->id, $options); } + + # If the state has been changed to action scheduled and they've said + # they want to raise a defect, consider the report to be inspected. + if ($problem->state eq 'action scheduled' && $c->get_param('raise_defect') && !$problem->get_extra_metadata('inspected')) { + $update_params{extra} = { 'defect_raised' => 1 }; + $problem->set_extra_metadata( inspected => 1 ); + $c->forward( '/admin/log_edit', [ $problem->id, 'problem', 'inspected' ] ); + } } $problem->non_public($c->get_param('non_public') ? 1 : 0); diff --git a/t/app/controller/report_inspect.t b/t/app/controller/report_inspect.t index c10fe7f94..367327c16 100644 --- a/t/app/controller/report_inspect.t +++ b/t/app/controller/report_inspect.t @@ -246,7 +246,7 @@ FixMyStreet::override_config { $user->update; }; - subtest "test update is required when instructing" => sub { + subtest "test public update is required if include_update is checked" => sub { $report->update; $report->comments->delete_all; $mech->get_ok("/report/$report_id"); @@ -913,6 +913,41 @@ FixMyStreet::override_config { $contact2->unset_extra_metadata('assigned_users_only'); $contact2->update; }; + + subtest 'instruct defect' => sub { + $user->user_body_permissions->create({ body => $oxon, permission_type => 'report_instruct' }); + $mech->get_ok("/report/$report2_id"); + $mech->submit_form_ok({ button => 'save', with_fields => { + public_update => "This is a public update.", include_update => "1", + state => 'action scheduled', raise_defect => 1, + } }); + $report2->discard_changes; + is $report2->get_extra_metadata('inspected'), 1, 'report marked as inspected'; + $mech->get_ok("/report/$report2_id"); + my $meta = $mech->extract_update_metas; + like $meta->[0], qr/State changed to: Action scheduled/, 'First update mentions action scheduled'; + like $meta->[1], qr/Posted by .*defect raised/, 'Update mentions defect raised'; + my $log_entry = $report2->inspection_log_entry; + is $log_entry->object_id, $report2_id, 'Log entry has correct ID'; + is $log_entry->object_type, 'problem', 'Log entry has correct type'; + is $log_entry->action, 'inspected', 'Log entry has correct action'; + }; + + subtest "test update is required when instructing defect" => sub { + $report2->unset_extra_metadata('inspected'); + $report2->update; + $report2->inspection_log_entry->delete; + $report2->comments->delete_all; + $mech->get_ok("/report/$report2_id"); + $mech->submit_form_ok({ button => 'save', with_fields => { + public_update => "", include_update => "0", + state => 'action scheduled', raise_defect => 1, + } }); + is_deeply $mech->page_errors, [ "Please provide a public update for this report." ], 'errors match'; + $report2->discard_changes; + is $report2->comments->count, 0, "Update wasn't created"; + is $report2->get_extra_metadata('inspected'), undef, 'report not marked as inspected'; + }; }; done_testing(); diff --git a/templates/web/base/report/_inspect.html b/templates/web/base/report/_inspect.html index 30848b5d4..f7d8cc056 100644 --- a/templates/web/base/report/_inspect.html +++ b/templates/web/base/report/_inspect.html @@ -34,6 +34,7 @@ <label for="state">[% loc('State') %]</label> [% INCLUDE 'report/inspect/state_groups_select.html' %] </p> + [% TRY %][% INCLUDE 'report/inspect/_raise_defect.html' %][% CATCH file %][% END %] <div id="js-duplicate-reports" class="[% "hidden" UNLESS problem.duplicate_of %]"> <input type="hidden" name="duplicate_of" value="[% problem.duplicate_of.id %]"> <p class="[% "hidden" UNLESS problem.duplicate_of %]"><strong>[% loc('Duplicate of') %]</strong></p> @@ -70,6 +71,8 @@ [% INCLUDE 'report/inspect/public_update.html' %] [% END %] + [% TRY %][% INCLUDE 'report/inspect/_inspected.html' %][% CATCH file %][% END %] + <p> <input type="hidden" name="token" value="[% csrf_token %]" /> [% IF permissions.planned_reports %] diff --git a/templates/web/oxfordshire/report/inspect/_inspected.html b/templates/web/oxfordshire/report/inspect/_inspected.html new file mode 100644 index 000000000..58d6c1528 --- /dev/null +++ b/templates/web/oxfordshire/report/inspect/_inspected.html @@ -0,0 +1,7 @@ +[% IF problem.get_extra_metadata('inspected') %] +[% IF problem.whensent %] + <p>[% loc("<strong>Note:</strong> This report has been sent onwards for action. Any changes made won't be passed on.") %]</p> +[% ELSE %] + <p>[% loc("<strong>Note:</strong> This report hasn't yet been sent onwards for action. Any changes made may not be passed on.") %]</p> +[% END %] +[% END %] diff --git a/templates/web/oxfordshire/report/inspect/_raise_defect.html b/templates/web/oxfordshire/report/inspect/_raise_defect.html new file mode 100644 index 000000000..5783def48 --- /dev/null +++ b/templates/web/oxfordshire/report/inspect/_raise_defect.html @@ -0,0 +1,11 @@ +[% IF permissions.report_instruct AND NOT problem.get_extra_metadata('inspected') %] +<div id="js-inspect-action-scheduled" class="[% "hidden" UNLESS problem.state == 'action scheduled' %]"> + <p>[% loc('Do you want to automatically raise a defect?') %]</p> + <p class="segmented-control segmented-control--radio"> + <input type="radio" name="raise_defect" id="raise_defect_yes" value="1"> + <label class="btn" for="raise_defect_yes">[% loc('Yes') %]</label> + <input type="radio" name="raise_defect" id="raise_defect_no" value="0"> + <label class="btn" for="raise_defect_no">[% loc('No') %]</label> + </p> +</div> +[% END %] diff --git a/web/cobrands/fixmystreet/staff.js b/web/cobrands/fixmystreet/staff.js index 4bbc0b11d..ec85dbb8d 100644 --- a/web/cobrands/fixmystreet/staff.js +++ b/web/cobrands/fixmystreet/staff.js @@ -1,4 +1,16 @@ fixmystreet.staff_set_up = { + action_scheduled_raise_defect: function() { + $("#report_inspect_form").find('[name=state]').on('change', function() { + if ($(this).val() !== "action scheduled") { + $("#js-inspect-action-scheduled").addClass("hidden"); + $('#raise_defect_yes').prop('required', false); + } else { + $("#js-inspect-action-scheduled").removeClass("hidden"); + $('#raise_defect_yes').prop('required', true); + } + }); + }, + list_item_actions: function() { $('#js-reports-list').on('click', ':submit', function(e) { e.preventDefault(); @@ -423,6 +435,7 @@ $(fixmystreet).on('display:report', function() { fixmystreet.staff_set_up.response_templates(); if ($("#report_inspect_form").length) { fixmystreet.staff_set_up.report_page_inspect(); + fixmystreet.staff_set_up.action_scheduled_raise_defect(); } }); |